[PATCH v2] kexec_file: skip checksum verification when safe
Michał Cłapiński
mclapinski at google.com
Tue Jun 2 08:43:54 PDT 2026
On Tue, Jun 2, 2026 at 5:16 PM Pratyush Yadav <pratyush at kernel.org> wrote:
>
> On Tue, Jun 02 2026, Michal Clapinski wrote:
>
> > Checksum verification is needed
> > 1. for crash kernels. In a crash, we can't be sure the kernel is
> > intact.
> > 2. if we're worried about relocating the kernel into a region used by
> > some DMA that wasn't properly cancelled.
> >
> > If KHO is enabled then relocations will happen to KHO scratch, which
> > is free from DMA regions.
> > If we used CMA to allocate segments then relocations are not going to
> > happen at all.
> > Therefore, we can safely disable checksum verification in both of those
> > cases.
> >
> > Instead of adding a new variable to purgatory, just skip adding regions
> > and save the default value of SHA256 hash.
> >
> > Saves ~250ms on my 4.0 GHz CPU. This is an important saving for the
> > live-update project.
> >
> > Signed-off-by: Michal Clapinski <mclapinski at google.com>
> > ---
> > v2:
> > - also skip checksum verification if KHO is enabled
> > - small fixes from reviews
> >
> > My original idea was to do 2 changes:
> > 1. Skip checksum if all segments are CMA.
> > 2. If KHO is enabled, allocate the kernel inside kho_scratch using CMA.
> >
> > This way we could skip both relocations and checksum verification when
> > KHO is enabled.
> > But I realized that step 2 might not be possible on warm boots.
>
> AFAIU we only relocate into scratch since relocating anywhere else might
> over-write preserved memory. If there is no relocation, there is no need
> for the kernel image to be in scratch, since the image won't be
> preserved memory anyway.
>
> So perhaps we can just use CMA directly, and only fall back to
> kho_locate_mem_hole() if that fails? This should be a simple enough
> change.
I agree that it will work. However, the user would need to have CMA
memory and it would need to have enough contiguous memory available.
Do you think running out of CMA memory is a real problem?
> Do you know how much time we can save by skipping relocations? I would
> guess it is in the hundreds of milliseconds.
It's smaller than the variance between runs. Maybe 10ms. Everything
between exiting the old kernel and TSC initialization in the new
kernel takes ~70ms.
Theoretically if we didn't have to do relocations, we could try
unpacking the kernel before kexec, which would save a little bit more
time. But again, definitely less than 0.1s.
> Can you try this (COMPLETELY UNTESTED) patch out and see if it works and
> if it further improves kexec time?
>
> --- 8< ---
> diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
> index 2bfbb2d144e6..0ccc7b6d67c1 100644
> --- a/kernel/kexec_file.c
> +++ b/kernel/kexec_file.c
> @@ -720,14 +720,6 @@ int kexec_locate_mem_hole(struct kexec_buf *kbuf)
> if (kbuf->mem != KEXEC_BUF_MEM_UNKNOWN)
> return 0;
>
> - /*
> - * If KHO is active, only use KHO scratch memory. All other memory
> - * could potentially be handed over.
> - */
> - ret = kho_locate_mem_hole(kbuf, locate_mem_hole_callback);
> - if (ret <= 0)
> - return ret;
> -
> /*
> * Try to find a free physically contiguous block of memory first. With that, we
> * can avoid any copying at kexec time.
> @@ -735,6 +727,14 @@ int kexec_locate_mem_hole(struct kexec_buf *kbuf)
> if (!kexec_alloc_contig(kbuf))
> return 0;
>
> + /*
> + * If KHO is active and relocations are to be done,, only use KHO
> + * scratch memory. All other memory could potentially be handed over.
> + */
> + ret = kho_locate_mem_hole(kbuf, locate_mem_hole_callback);
> + if (ret <= 0)
> + return ret;
> +
> if (!IS_ENABLED(CONFIG_ARCH_KEEP_MEMBLOCK))
> ret = kexec_walk_resources(kbuf, locate_mem_hole_callback);
> else
> --- >8 ---
>
> Of course this is not directly related to this patch so it shouldn't
> block it, but I reckon we might be able to squeeze a bit more
> performance out this way as a follow up.
>
> > I have no idea how to fix that (except weird ideas like 2 kho_scratches
> > that we swap on every warm boot), so I decided to just skip checksum
> > verification when KHO is enabled. This unfortunately means relocations
> > will still happen.
> > ---
> > kernel/kexec_file.c | 27 +++++++++++++++++++++++++++
> > 1 file changed, 27 insertions(+)
> >
> > diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
> > index 2bfbb2d144e6..db25a14692ab 100644
> > --- a/kernel/kexec_file.c
> > +++ b/kernel/kexec_file.c
> > @@ -27,6 +27,7 @@
> > #include <linux/syscalls.h>
> > #include <linux/vmalloc.h>
> > #include <linux/dma-map-ops.h>
> > +#include <linux/kexec_handover.h>
> > #include "kexec_internal.h"
> >
> > #ifdef CONFIG_KEXEC_SIG
> > @@ -798,6 +799,16 @@ int kexec_add_buffer(struct kexec_buf *kbuf)
> > return 0;
> > }
> >
> > +static bool kexec_only_cma_segments(struct kimage *image)
> > +{
> > + for (int i = 0; i < image->nr_segments; i++) {
> > + if (!image->segment_cma[i])
> > + return false;
> > + }
> > +
> > + return true;
> > +}
> > +
> > /* Calculate and store the digest of segments */
> > static int kexec_calculate_store_digests(struct kimage *image)
> > {
> > @@ -822,6 +833,21 @@ static int kexec_calculate_store_digests(struct kimage *image)
> >
> > sha256_init(&sctx);
> >
> > + /*
> > + * If KHO is enabled, the destinations are located in KHO scratch.
> > + * KHO scratch can only contain early boot allocations and movable
> > + * allocations. That means there is no risk of memory corruption by
> > + * uncancelled DMA.
> > + *
> > + * If all segments were loaded into contiguous memory, there will be no
> > + * relocations at all, so also no risk no corruption.
>
> Typo: "so also no risk *of* corruption".
>
> We can fix that up when applying I think, so no need for a v3 just for
> this.
>
> Other than this,
>
> Reviewed-by: Pratyush Yadav (Google) <pratyush at kernel.org>
>
> > + */
> > + if (image->type != KEXEC_TYPE_CRASH &&
> > + (kho_is_enabled() || kexec_only_cma_segments(image))) {
> > + pr_debug("disabling checksum verification in purgatory\n");
> > + goto skip_checksum;
> > + }
> > +
> > for (j = i = 0; i < image->nr_segments; i++) {
> > struct kexec_segment *ksegment;
> >
> > @@ -867,6 +893,7 @@ static int kexec_calculate_store_digests(struct kimage *image)
> > j++;
> > }
> >
> > +skip_checksum:
> > sha256_final(&sctx, digest);
> >
> > ret = kexec_purgatory_get_set_symbol(image, "purgatory_sha_regions",
>
> --
> Regards,
> Pratyush Yadav
More information about the kexec
mailing list