diff --git a/arch/powerpc/kernel/kexec_elf_64.c b/arch/powerpc/kernel/kexec_elf_64.c
index 5d2b7036fee7..abbad484d7b2 100644
--- a/arch/powerpc/kernel/kexec_elf_64.c
+++ b/arch/powerpc/kernel/kexec_elf_64.c
@@ -311,7 +311,7 @@ static int elf_exec_load(struct kimage *image, struct elfhdr *ehdr,
 				       (char *) elf_info->buffer + phdr->p_offset,
 				       size, phdr->p_memsz, phdr->p_align,
 				       phdr->p_paddr + base, ppc64_rma_size,
-				       false, &load_addr);
+				       false, true, &load_addr);
 		if (ret)
 			goto out;
 
@@ -487,7 +487,7 @@ void *elf64_load(struct kimage *image, char *kernel_buf,
 	if (initrd != NULL) {
 		ret = kexec_add_buffer(image, initrd, initrd_len, initrd_len,
 				       PAGE_SIZE, 0, ppc64_rma_size, false,
-				       &initrd_load_addr);
+				       true, &initrd_load_addr);
 		if (ret)
 			goto out;
 
@@ -564,7 +564,7 @@ void *elf64_load(struct kimage *image, char *kernel_buf,
 	fdt_pack(fdt);
 
 	ret = kexec_add_buffer(image, fdt, fdt_size, fdt_size, PAGE_SIZE, 0,
-			       ppc64_rma_size, true, &fdt_load_addr);
+			       ppc64_rma_size, true, true, &fdt_load_addr);
 	if (ret)
 		goto out;
 
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index 9ef978d69c22..c8b16f2ca321 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -643,7 +643,7 @@ int crash_load_segments(struct kimage *image)
 		 */
 		ret = kexec_add_buffer(image, (char *)&crash_zero_bytes,
 				       sizeof(crash_zero_bytes), src_sz,
-				       PAGE_SIZE, 0, -1, 0,
+				       PAGE_SIZE, 0, -1, false, true,
 				       &image->arch.backup_load_addr);
 		if (ret)
 			return ret;
@@ -660,7 +660,7 @@ int crash_load_segments(struct kimage *image)
 	image->arch.elf_headers_sz = elf_sz;
 
 	ret = kexec_add_buffer(image, (char *)elf_addr, elf_sz, elf_sz,
-			ELF_CORE_HEADER_ALIGN, 0, -1, 0,
+			ELF_CORE_HEADER_ALIGN, 0, -1, false, true,
 			&image->arch.elf_load_addr);
 	if (ret) {
 		vfree((void *)image->arch.elf_headers);
diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c
index f2356bda2b05..f9016be44da6 100644
--- a/arch/x86/kernel/kexec-bzimage64.c
+++ b/arch/x86/kernel/kexec-bzimage64.c
@@ -420,7 +420,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
 
 	ret = kexec_add_buffer(image, (char *)params, params_misc_sz,
 			       params_misc_sz, 16, MIN_BOOTPARAM_ADDR,
-			       ULONG_MAX, 1, &bootparam_load_addr);
+			       ULONG_MAX, true, true, &bootparam_load_addr);
 	if (ret)
 		goto out_free_params;
 	pr_debug("Loaded boot_param, command line and misc at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
@@ -434,7 +434,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
 
 	ret = kexec_add_buffer(image, kernel_buf,
 			       kernel_bufsz, kernel_memsz, kernel_align,
-			       MIN_KERNEL_LOAD_ADDR, ULONG_MAX, 1,
+			       MIN_KERNEL_LOAD_ADDR, ULONG_MAX, true, true,
 			       &kernel_load_addr);
 	if (ret)
 		goto out_free_params;
@@ -446,7 +446,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
 	if (initrd) {
 		ret = kexec_add_buffer(image, initrd, initrd_len, initrd_len,
 				       PAGE_SIZE, MIN_INITRD_LOAD_ADDR,
-				       ULONG_MAX, 1, &initrd_load_addr);
+				       ULONG_MAX, true, true, &initrd_load_addr);
 		if (ret)
 			goto out_free_params;
 
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 72db95c623b3..131b1fc7820e 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -98,6 +98,9 @@ struct kexec_segment {
 	size_t bufsz;
 	unsigned long mem;
 	size_t memsz;
+
+	/* Whether this segment is part of the checksum calculation. */
+	bool do_checksum;
 };
 
 #ifdef CONFIG_COMPAT
@@ -217,7 +220,7 @@ int kexec_locate_mem_hole(struct kimage *image, unsigned long size,
 extern int kexec_add_buffer(struct kimage *image, char *buffer,
 			    unsigned long bufsz, unsigned long memsz,
 			    unsigned long buf_align, unsigned long buf_min,
-			    unsigned long buf_max, bool top_down,
+			    unsigned long buf_max, bool top_down, bool checksum,
 			    unsigned long *load_addr);
 extern struct page *kimage_alloc_control_pages(struct kimage *image,
 						unsigned int order);
@@ -334,7 +337,7 @@ int kexec_add_handover_buffer(struct kimage *image, void *buffer,
 			      unsigned long bufsz, unsigned long memsz,
 			      unsigned long buf_align, unsigned long buf_min,
 			      unsigned long buf_max, bool top_down,
-			      unsigned long *load_addr);
+			      bool checksum, unsigned long *load_addr);
 int __weak kexec_get_handover_buffer(void **addr, unsigned long *size);
 int __weak kexec_free_handover_buffer(void);
 #else
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index d6ba702654f5..3aa829a78f50 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -146,6 +146,7 @@ int __weak arch_kexec_add_handover_buffer(struct kimage *image,
  * @buf_min:	Minimum address where buffer can be placed.
  * @buf_max:	Maximum address where buffer can be placed.
  * @top_down:	Find the highest available memory position for the buffer?
+ * @checksum:	Should this buffer checksum be verified by the purgatory?
  * @load_addr:	On successful return, set to the physical memory address of the
  * 		buffer in the next kernel.
  *
@@ -157,7 +158,7 @@ int kexec_add_handover_buffer(struct kimage *image, void *buffer,
 			      unsigned long bufsz, unsigned long memsz,
 			      unsigned long buf_align, unsigned long buf_min,
 			      unsigned long buf_max, bool top_down,
-			      unsigned long *load_addr)
+			      bool checksum, unsigned long *load_addr)
 {
 	int ret;
 
@@ -165,7 +166,7 @@ int kexec_add_handover_buffer(struct kimage *image, void *buffer,
 		return -ENOTSUPP;
 
 	ret = kexec_add_buffer(image, buffer, bufsz, memsz, buf_align, buf_min,
-			       buf_max, top_down, load_addr);
+			       buf_max, top_down, checksum, load_addr);
 	if (ret)
 		return ret;
 
@@ -590,7 +591,7 @@ int kexec_locate_mem_hole(struct kimage *image, unsigned long size,
 int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz,
 		     unsigned long memsz, unsigned long buf_align,
 		     unsigned long buf_min, unsigned long buf_max,
-		     bool top_down, unsigned long *load_addr)
+		     bool top_down, bool checksum, unsigned long *load_addr)
 {
 
 	struct kexec_segment *ksegment;
@@ -630,6 +631,7 @@ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz,
 	ksegment->bufsz = bufsz;
 	ksegment->mem = addr;
 	ksegment->memsz = size;
+	ksegment->do_checksum = checksum;
 	image->nr_segments++;
 	*load_addr = ksegment->mem;
 	return 0;
@@ -645,7 +647,6 @@ static int kexec_calculate_store_digests(struct kimage *image)
 	char *digest;
 	void *zero_buf;
 	struct kexec_sha_region *sha_regions;
-	struct purgatory_info *pi = &image->purgatory_info;
 
 	zero_buf = __va(page_to_pfn(ZERO_PAGE(0)) << PAGE_SHIFT);
 	zero_buf_sz = PAGE_SIZE;
@@ -685,11 +686,7 @@ static int kexec_calculate_store_digests(struct kimage *image)
 		struct kexec_segment *ksegment;
 
 		ksegment = &image->segment[i];
-		/*
-		 * Skip purgatory as it will be modified once we put digest
-		 * info in purgatory.
-		 */
-		if (ksegment->kbuf == pi->purgatory_buf)
+		if (!ksegment->do_checksum)
 			continue;
 
 		ret = crypto_shash_update(desc, ksegment->kbuf,
@@ -866,9 +863,12 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
 	if (buf_align < bss_align)
 		buf_align = bss_align;
 
-	/* Add buffer to segment list */
+	/*
+	 * Add buffer to segment list. Don't checksum the segment as
+	 * it will be modified once we put digest info in purgatory.
+	 */
 	ret = kexec_add_buffer(image, purgatory_buf, buf_sz, memsz,
-				buf_align, min, max, top_down,
+				buf_align, min, max, top_down, false,
 				&pi->purgatory_load_addr);
 	if (ret)
 		goto out;
