[PATCHv8,11/14] x86: Disable kexec if system has unaccepted memory
Commit Message
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 <kirill.shutemov@linux.intel.com>
---
arch/x86/include/asm/kexec.h | 5 +++++
arch/x86/mm/unaccepted_memory.c | 16 ++++++++++++++++
include/linux/kexec.h | 7 +++++++
kernel/kexec.c | 4 ++++
kernel/kexec_file.c | 4 ++++
5 files changed, 36 insertions(+)
@@ -189,6 +189,11 @@ 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
+#ifdef CONFIG_UNACCEPTED_MEMORY
+int arch_kexec_load(void);
+#define arch_kexec_load arch_kexec_load
+#endif
+
void arch_kexec_unprotect_crashkres(void);
#define arch_kexec_unprotect_crashkres arch_kexec_unprotect_crashkres
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/kexec.h>
#include <linux/memblock.h>
#include <linux/mm.h>
#include <linux/pfn.h>
@@ -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
@@ -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)
{
@@ -192,6 +192,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;
@@ -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;