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 we used CMA to allocate segments then 1. we're not working with a crash kernel. 2. relocations are not going to happen. Therefore, we can safely disable checksum verification. 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. Signed-off-by: Michal Clapinski <[email protected]> --- kernel/kexec_file.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index 2bfbb2d144e6..2dc8b0435fe6 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -808,6 +808,7 @@ static int kexec_calculate_store_digests(struct kimage *image) void *zero_buf; struct kexec_sha_region *sha_regions; struct purgatory_info *pi = &image->purgatory_info; + bool can_skip_checksum = true; if (!IS_ENABLED(CONFIG_ARCH_SUPPORTS_KEXEC_PURGATORY)) return 0; @@ -822,6 +823,23 @@ static int kexec_calculate_store_digests(struct kimage *image) sha256_init(&sctx); + /* + * If all segments were loaded into contiguous memory, there will be no + * relocations. In that case there is no risk of memory corruption by + * uncancelled DMA and we can skip checksum calculation. + */ + for (i = 0; i < image->nr_segments; i++) { + if (!image->segment_cma[i]) { + can_skip_checksum = false; + break; + } + } + + if (can_skip_checksum) { + pr_info("disabling checksum verification in purgatory\n"); + goto skip_checksum; + } + for (j = i = 0; i < image->nr_segments; i++) { struct kexec_segment *ksegment; @@ -867,6 +885,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", -- 2.54.0.929.g9b7fa37559-goog
