From 820c5c338451079677510d4183ba5d5dc314c030 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Tue, 10 May 2022 19:02:18 +0300 Subject: [PATCH] x86: Disable kexec if system has unaccepted memory On kexec, the target kernel has to know what memory has been accepted. Information in EFI map is out of date and cannot be used. boot_params.unaccepted_memory can be used to pass the bitmap between two kernels on kexec, but the use-case is not yet implemented. Disable kexec on machines with unaccepted memory for now. Signed-off-by: Kirill A. Shutemov --- arch/x86/include/asm/kexec.h | 3 +++ arch/x86/mm/unaccepted_memory.c | 16 ++++++++++++++++ include/linux/kexec.h | 7 +++++++ kernel/kexec.c | 4 ++++ kernel/kexec_file.c | 4 ++++ 5 files changed, 34 insertions(+) diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h index a3760ca796aa2..89693684a7d1f 100644 --- a/arch/x86/include/asm/kexec.h +++ b/arch/x86/include/asm/kexec.h @@ -189,6 +189,9 @@ extern void arch_kexec_pre_free_pages(void *vaddr, unsigned int pages); void arch_kexec_protect_crashkres(void); #define arch_kexec_protect_crashkres arch_kexec_protect_crashkres +int arch_kexec_load(void); +#define arch_kexec_load arch_kexec_load + void arch_kexec_unprotect_crashkres(void); #define arch_kexec_unprotect_crashkres arch_kexec_unprotect_crashkres diff --git a/arch/x86/mm/unaccepted_memory.c b/arch/x86/mm/unaccepted_memory.c index 566c3a72aee8b..529c3fd1dab32 100644 --- a/arch/x86/mm/unaccepted_memory.c +++ b/arch/x86/mm/unaccepted_memory.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only +#include #include #include #include @@ -98,3 +99,18 @@ bool range_contains_unaccepted_memory(phys_addr_t start, phys_addr_t end) return ret; } + +#ifdef CONFIG_KEXEC_CORE +int arch_kexec_load(void) +{ + if (!boot_params.unaccepted_memory) + return 0; + + /* + * TODO: Information on memory acceptance status has to be communicated + * between kernel. + */ + pr_warn_once("Disable kexec: not yet supported on systems with unaccepted memory\n"); + return -EOPNOTSUPP; +} +#endif diff --git a/include/linux/kexec.h b/include/linux/kexec.h index 13e6c4b58f07d..ab613089db536 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -444,6 +444,13 @@ static inline void arch_kexec_protect_crashkres(void) { } static inline void arch_kexec_unprotect_crashkres(void) { } #endif +#ifndef arch_kexec_load +static inline int arch_kexec_load(void) +{ + return 0; +} +#endif + #ifndef page_to_boot_pfn static inline unsigned long page_to_boot_pfn(struct page *page) { diff --git a/kernel/kexec.c b/kernel/kexec.c index b5e40f0697681..352b3742f07a6 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -195,6 +195,10 @@ static inline int kexec_load_check(unsigned long nr_segments, { int result; + result = arch_kexec_load(); + if (result) + return result; + /* We only trust the superuser with rebooting the system. */ if (!capable(CAP_SYS_BOOT) || kexec_load_disabled) return -EPERM; diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index 1d546dc97c502..2e27340a1ac55 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -329,6 +329,10 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd, int ret = 0, i; struct kimage **dest_image, *image; + ret = arch_kexec_load(); + if (ret) + return ret; + /* We only trust the superuser with rebooting the system. */ if (!capable(CAP_SYS_BOOT) || kexec_load_disabled) return -EPERM;