On Tue, Oct 21, 2025 at 08:57:13PM -0400, Pasha Tatashin wrote: > Allow kernel to drive finalize and abort without requiring triggers > from the userspace. > > Signed-off-by: Pasha Tatashin <[email protected]> > Reviewed-by: Pratyush Yadav <[email protected]>
Reviewed-by: Mike Rapoport (Microsoft) <[email protected]> > --- > include/linux/kexec_handover.h | 15 +++++++ > kernel/kexec_handover.c | 75 +++++++++++++++++++++------------- > 2 files changed, 61 insertions(+), 29 deletions(-) > > diff --git a/include/linux/kexec_handover.h b/include/linux/kexec_handover.h > index 25042c1d8d54..04d0108db98e 100644 > --- a/include/linux/kexec_handover.h > +++ b/include/linux/kexec_handover.h > @@ -67,6 +67,10 @@ void kho_memory_init(void); > > void kho_populate(phys_addr_t fdt_phys, u64 fdt_len, phys_addr_t > scratch_phys, > u64 scratch_len); > + > +int kho_finalize(void); > +int kho_abort(void); > + > #else > static inline bool kho_is_enabled(void) > { > @@ -139,6 +143,17 @@ static inline void kho_populate(phys_addr_t fdt_phys, > u64 fdt_len, > phys_addr_t scratch_phys, u64 scratch_len) > { > } > + > +static inline int kho_finalize(void) > +{ > + return -EOPNOTSUPP; > +} > + > +static inline int kho_abort(void) > +{ > + return -EOPNOTSUPP; > +} > + > #endif /* CONFIG_KEXEC_HANDOVER */ > > #endif /* LINUX_KEXEC_HANDOVER_H */ > diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c > index de4466b47455..6458f369a346 100644 > --- a/kernel/kexec_handover.c > +++ b/kernel/kexec_handover.c > @@ -1087,7 +1087,7 @@ static int kho_out_update_debugfs_fdt(void) > return err; > } > > -static int kho_abort(void) > +static int __kho_abort(void) > { > int err; > unsigned long order; > @@ -1120,7 +1120,27 @@ static int kho_abort(void) > return err; > } > > -static int kho_finalize(void) > +int kho_abort(void) > +{ > + int ret = 0; > + > + if (!kho_enable) > + return -EOPNOTSUPP; > + > + guard(mutex)(&kho_out.lock); > + if (!kho_out.finalized) > + return -ENOENT; > + > + ret = __kho_abort(); > + if (ret) > + return ret; > + > + kho_out.finalized = false; > + > + return kho_out_update_debugfs_fdt(); > +} > + > +static int __kho_finalize(void) > { > int err = 0; > u64 *preserved_mem_map; > @@ -1163,12 +1183,32 @@ static int kho_finalize(void) > abort: > if (err) { > pr_err("Failed to convert KHO state tree: %d\n", err); > - kho_abort(); > + __kho_abort(); > } > > return err; > } > > +int kho_finalize(void) > +{ > + int ret; > + > + if (!kho_enable) > + return -EOPNOTSUPP; > + > + guard(mutex)(&kho_out.lock); > + if (kho_out.finalized) > + return -EEXIST; > + > + ret = __kho_finalize(); > + if (ret) > + return ret; > + > + kho_out.finalized = true; > + > + return kho_out_update_debugfs_fdt(); > +} > + > static int kho_out_finalize_get(void *data, u64 *val) > { > mutex_lock(&kho_out.lock); > @@ -1178,35 +1218,12 @@ static int kho_out_finalize_get(void *data, u64 *val) > return 0; > } > > -static int kho_out_finalize_set(void *data, u64 _val) > +static int kho_out_finalize_set(void *data, u64 val) > { > - int ret = 0; > - bool val = !!_val; > - > - mutex_lock(&kho_out.lock); > - > - if (val == kho_out.finalized) { > - if (kho_out.finalized) > - ret = -EEXIST; > - else > - ret = -ENOENT; > - goto unlock; > - } > - > if (val) > - ret = kho_finalize(); > + return kho_finalize(); > else > - ret = kho_abort(); > - > - if (ret) > - goto unlock; > - > - kho_out.finalized = val; > - ret = kho_out_update_debugfs_fdt(); > - > -unlock: > - mutex_unlock(&kho_out.lock); > - return ret; > + return kho_abort(); > } > > DEFINE_DEBUGFS_ATTRIBUTE(fops_kho_out_finalize, kho_out_finalize_get, > -- > 2.51.0.915.g61a8936c21-goog > -- Sincerely yours, Mike.

