Re: [RFC PATCH 2/7] liveupdate: parse the incoming handover tree before late_time_init()
From: Ankit Soni
Date: Fri Oct 09 2026 - 10:06:44 EST
Hi Mike
On Thu, Oct 08, 2026 at 09:59:40AM +0200, Mike Rapoport wrote:
> Hi,
>
> On Mon, Oct 05, 2026 at 06:40:12AM +0000, Ankit Soni wrote:
> > LUO parses the handover tree from an early_initcall, which runs inside
> > rest_init() -- the last statement of start_kernel(). Anything earlier in
> > start_kernel() cannot see the incoming state, and cannot tell that it
> > cannot see it: luo_flb_retrieve_one() returns -ENODATA both before the
> > parse and when the previous kernel handed nothing over.
> >
> > On x86 the IOMMU is such a consumer, because it is also the interrupt
> > remapping provider. amd_iommu_prepare() runs from late_time_init() via
> > enable_IR_x2apic() -> irq_remapping_prepare(), and reaches
> > init_iommu_one_late() long before any initcall.
> >
> > Fix the ordering rather than teaching each consumer to cope. Call the
> > parse directly from start_kernel(), immediately before late_time_init().
>
> Why do you suggest to call it exactly here?
> Order of the calls in start_kernel() is quite sensitive and placing a call
> in a certain place needs more elaborate explanation.
>
Fair, the commit message asserts the placement without justifying it elaborately.
The slot is bounded on both sides, and within those bounds I took the latest
point. I will fold commit message in respin.
Earliest:
luo_early_startup() ends in kho_restore_free(), which goes through
kho_restore_folio() and folio_put(), so it needs struct page and a working
page allocator. It also reads a preserved page, and kho_memory_init() is
what calls kho_mem_retrieve() to take those pages out of circulation; that
runs from mm_core_init(). Reading the handover FDT is not a constraint, as
kho_populate() records it from setup_arch() via parse_setup_data().
Second bound: luo_restore_fail() is a panic(), so running before
console_init() would panic a failed handover with nothing on the console,
which is exactly when the message is wanted.
Latest: on x86 the IOMMU is the interrupt remapping provider, so both halves
of its early init run inside late_time_init():
x86_late_time_init() -> apic_intr_mode_init() -> x86_64_probe_apic()
-> enable_IR_x2apic()
-> irq_remapping_prepare() -> amd_iommu_prepare()
-> early_amd_iommu_init()
init_iommu_one_late(), __disable_iommus(true)
-> irq_remapping_enable() -> amd_iommu_enable()
-> early_enable_iommus() -> reuse_device_table()
All three sites that ask whether this unit was handed over sit on that path,
and all of it is before any initcall.
So the window is between console_init() and late_time_init(). I placed the
call at the end of it, on the grounds that it perturbs the least: every
existing call in that window keeps running exactly as before, and the only
code that can observe the new call is late_time_init() and later. Nothing in
the window consumes LUO state, so moving the call earlier would widen the
exposure without buying anything.
Anywhere in that window works for the AMD case, so if you would rather see
it somewhere else, I am happy to move it.
> > Rename it to liveupdate_init_early() at the same time, since
> > liveupdate_early_init() was named after the early_initcall that no longer
> > exists.
>
> No strong feeling about this, but we do have other _early_init() functions
> unrelated to initcalls.
>
Will drop this.
Thanks,
Ankit
> > Signed-off-by: Ankit Soni <Ankit.Soni@xxxxxxx>
> > ---
> > include/linux/liveupdate.h | 4 ++++
> > init/main.c | 2 ++
> > kernel/liveupdate/luo_core.c | 5 +----
> > 3 files changed, 7 insertions(+), 4 deletions(-)
>
> --
> Sincerely yours,
> Mike.