diff options
Diffstat (limited to 'drivers/firmware/efi')
-rw-r--r-- | drivers/firmware/efi/Kconfig | 7 | ||||
-rw-r--r-- | drivers/firmware/efi/efi-init.c | 29 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/x86-stub.c | 14 |
3 files changed, 38 insertions, 12 deletions
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index d528c94c5859..29e0729299f5 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig @@ -267,9 +267,10 @@ config OVMF_DEBUG_LOG bool "Expose OVMF firmware debug log via sysfs" depends on EFI help - Recent OVMF versions (edk2-stable202508 + newer) can write - their debug log to a memory buffer. This driver exposes the - log content via sysfs (/sys/firmware/efi/ovmf_debug_log). + Recent versions of the Open Virtual Machine Firmware + (edk2-stable202508 + newer) can write their debug log to a memory + buffer. This driver exposes the log content via sysfs + (/sys/firmware/efi/ovmf_debug_log). config UNACCEPTED_MEMORY bool diff --git a/drivers/firmware/efi/efi-init.c b/drivers/firmware/efi/efi-init.c index a00e07b853f2..a65c2d5b9e7b 100644 --- a/drivers/firmware/efi/efi-init.c +++ b/drivers/firmware/efi/efi-init.c @@ -12,6 +12,7 @@ #include <linux/efi.h> #include <linux/fwnode.h> #include <linux/init.h> +#include <linux/kexec_handover.h> #include <linux/memblock.h> #include <linux/mm_types.h> #include <linux/of.h> @@ -164,12 +165,32 @@ static __init void reserve_regions(void) pr_info("Processing EFI memory map:\n"); /* - * Discard memblocks discovered so far: if there are any at this - * point, they originate from memory nodes in the DT, and UEFI - * uses its own memory map instead. + * Discard memblocks discovered so far except for KHO scratch + * regions. Most memblocks at this point originate from memory nodes + * in the DT and UEFI uses its own memory map instead. However, if + * KHO is enabled, scratch regions, which are good known memory + * must be preserved. */ memblock_dump_all(); - memblock_remove(0, PHYS_ADDR_MAX); + + if (is_kho_boot()) { + struct memblock_region *r; + + /* Remove all non-KHO regions */ + for_each_mem_region(r) { + if (!memblock_is_kho_scratch(r)) { + memblock_remove(r->base, r->size); + r--; + } + } + } else { + /* + * KHO is disabled. Discard memblocks discovered so far: + * if there are any at this point, they originate from memory + * nodes in the DT, and UEFI uses its own memory map instead. + */ + memblock_remove(0, PHYS_ADDR_MAX); + } for_each_efi_memory_desc(md) { paddr = md->phys_addr; diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c index cafc90d4caaf..761121a77f9e 100644 --- a/drivers/firmware/efi/libstub/x86-stub.c +++ b/drivers/firmware/efi/libstub/x86-stub.c @@ -300,7 +300,7 @@ efi_status_t efi_adjust_memory_range_protection(unsigned long start, return EFI_SUCCESS; /* - * Don't modify memory region attributes, they are + * Don't modify memory region attributes, if they are * already suitable, to lower the possibility to * encounter firmware bugs. */ @@ -315,11 +315,13 @@ efi_status_t efi_adjust_memory_range_protection(unsigned long start, next = desc.base_address + desc.length; /* - * Only system memory is suitable for trampoline/kernel image placement, - * so only this type of memory needs its attributes to be modified. + * Only system memory and more reliable memory are suitable for + * trampoline/kernel image placement. So only those memory types + * may need to have attributes modified. */ - if (desc.gcd_memory_type != EfiGcdMemoryTypeSystemMemory || + if ((desc.gcd_memory_type != EfiGcdMemoryTypeSystemMemory && + desc.gcd_memory_type != EfiGcdMemoryTypeMoreReliable) || (desc.attributes & (EFI_MEMORY_RO | EFI_MEMORY_XP)) == 0) continue; @@ -788,7 +790,9 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry, *kernel_entry = addr + entry; - return efi_adjust_memory_range_protection(addr, kernel_text_size); + return efi_adjust_memory_range_protection(addr, kernel_text_size) ?: + efi_adjust_memory_range_protection(addr + kernel_inittext_offset, + kernel_inittext_size); } static void __noreturn enter_kernel(unsigned long kernel_addr, |