Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

efi: support booting with kexec handover (KHO)

When KHO (Kexec HandOver) is enabled, it sets up scratch memory regions
early during device tree scanning. After kexec, the new kernel
exclusively uses this region for memory allocations during boot up to the
initialization of the page allocator

However, when booting with EFI, EFI's reserve_regions() uses
memblock_remove(0, PHYS_ADDR_MAX) to clear all memory regions before
rebuilding them from EFI data. This destroys KHO scratch regions and
their flags, thus causing a kernel panic, as there are no scratch memory
regions.

Instead of wholesale removal, iterate through memory regions and only
remove non-KHO ones. This preserves KHO scratch regions, which are good
known memory, while still allowing EFI to rebuild its memory map.

Link: https://lkml.kernel.org/r/b34da9fd50c89644cd4204136cfa6f5533445c56.1755721529.git.epetron@amazon.de
Signed-off-by: Evangelos Petrongonas <epetron@amazon.de>
Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Acked-by: Pratyush Yadav <pratyush@kernel.org>
Cc: Alexander Graf <graf@amazon.com>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Baoquan He <bhe@redhat.com>
Cc: Changyuan Lyu <changyuanl@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Evangelos Petrongonas and committed by
Andrew Morton
5b86af1d d6d51163

+25 -4
+25 -4
drivers/firmware/efi/efi-init.c
··· 12 12 #include <linux/efi.h> 13 13 #include <linux/fwnode.h> 14 14 #include <linux/init.h> 15 + #include <linux/kexec_handover.h> 15 16 #include <linux/memblock.h> 16 17 #include <linux/mm_types.h> 17 18 #include <linux/of.h> ··· 165 164 pr_info("Processing EFI memory map:\n"); 166 165 167 166 /* 168 - * Discard memblocks discovered so far: if there are any at this 169 - * point, they originate from memory nodes in the DT, and UEFI 170 - * uses its own memory map instead. 167 + * Discard memblocks discovered so far except for KHO scratch 168 + * regions. Most memblocks at this point originate from memory nodes 169 + * in the DT and UEFI uses its own memory map instead. However, if 170 + * KHO is enabled, scratch regions, which are good known memory 171 + * must be preserved. 171 172 */ 172 173 memblock_dump_all(); 173 - memblock_remove(0, PHYS_ADDR_MAX); 174 + 175 + if (is_kho_boot()) { 176 + struct memblock_region *r; 177 + 178 + /* Remove all non-KHO regions */ 179 + for_each_mem_region(r) { 180 + if (!memblock_is_kho_scratch(r)) { 181 + memblock_remove(r->base, r->size); 182 + r--; 183 + } 184 + } 185 + } else { 186 + /* 187 + * KHO is disabled. Discard memblocks discovered so far: 188 + * if there are any at this point, they originate from memory 189 + * nodes in the DT, and UEFI uses its own memory map instead. 190 + */ 191 + memblock_remove(0, PHYS_ADDR_MAX); 192 + } 174 193 175 194 for_each_efi_memory_desc(md) { 176 195 paddr = md->phys_addr;