]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
x86/kexec: Move relocate_kernel to kernel .data section
authorDavid Woodhouse <dwmw@amazon.co.uk>
Thu, 5 Dec 2024 15:05:14 +0000 (15:05 +0000)
committerIngo Molnar <mingo@kernel.org>
Fri, 6 Dec 2024 09:41:59 +0000 (10:41 +0100)
Now that the copy is executed instead of the original, the relocate_kernel
page can live in the kernel's .text section. This will allow subsequent
commits to actually add real data to it and clean up the code somewhat as
well as making the control page ROX.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Baoquan He <bhe@redhat.com>
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: Dave Young <dyoung@redhat.com>
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Link: https://lore.kernel.org/r/20241205153343.3275139-9-dwmw2@infradead.org
arch/x86/include/asm/sections.h
arch/x86/kernel/callthunks.c
arch/x86/kernel/machine_kexec_64.c
arch/x86/kernel/relocate_kernel_64.S
arch/x86/kernel/vmlinux.lds.S

index 3fa87e5e11aba92e17737164894de5a299431d6d..30e8ee7006f9a7a43d07a4647b0e8cc087496b5f 100644 (file)
@@ -5,6 +5,7 @@
 #include <asm-generic/sections.h>
 #include <asm/extable.h>
 
+extern char __relocate_kernel_start[], __relocate_kernel_end[];
 extern char __brk_base[], __brk_limit[];
 extern char __end_rodata_aligned[];
 
index 4656474567533bc9398e814ac8fd78df172cfdd1..51c3e0049152df87f8623d4b5e7c65687e3d5a1c 100644 (file)
@@ -139,9 +139,15 @@ static bool skip_addr(void *dest)
                return true;
 #endif
 #ifdef CONFIG_KEXEC_CORE
+# ifdef CONFIG_X86_64
+       if (dest >= (void *)__relocate_kernel_start &&
+           dest < (void *)__relocate_kernel_end)
+               return true;
+# else
        if (dest >= (void *)relocate_kernel &&
            dest < (void*)relocate_kernel + KEXEC_CONTROL_CODE_MAX_SIZE)
                return true;
+# endif
 #endif
 #ifdef CONFIG_XEN
        if (dest >= (void *)hypercall_page &&
index 9567347f7a9b483d2bf610a74bf0c1a069b05d2d..23dffdc070ddf5f8bc84287e19a69afe2342498a 100644 (file)
@@ -307,6 +307,8 @@ static void load_segments(void)
 int machine_kexec_prepare(struct kimage *image)
 {
        void *control_page = page_address(image->control_code_page);
+       unsigned long reloc_start = (unsigned long)__relocate_kernel_start;
+       unsigned long reloc_end = (unsigned long)__relocate_kernel_end;
        int result;
 
        /* Setup the identity mapped 64bit page table */
@@ -314,7 +316,7 @@ int machine_kexec_prepare(struct kimage *image)
        if (result)
                return result;
 
-       __memcpy(control_page, relocate_kernel, KEXEC_CONTROL_CODE_MAX_SIZE);
+       __memcpy(control_page, __relocate_kernel_start, reloc_end - reloc_start);
 
        set_memory_x((unsigned long)control_page, 1);
 
index d0a87b39db6a5e9ddf5777a2bd3e1bd28ddd785c..267004441665fabd4c77068b4fddc1de3614ba5a 100644 (file)
 #define CP_PA_BACKUP_PAGES_MAP DATA(0x30)
 #define CP_VA_CONTROL_PAGE     DATA(0x38)
 
-       .text
-       .align PAGE_SIZE
+       .section .text.relocate_kernel,"ax";
        .code64
-SYM_CODE_START_NOALIGN(relocate_range)
 SYM_CODE_START_NOALIGN(relocate_kernel)
        UNWIND_HINT_END_OF_STACK
        ANNOTATE_NOENDBR
@@ -341,6 +339,3 @@ SYM_CODE_START_LOCAL_NOALIGN(swap_pages)
        ret
        int3
 SYM_CODE_END(swap_pages)
-
-       .skip KEXEC_CONTROL_CODE_MAX_SIZE - (. - relocate_kernel), 0xcc
-SYM_CODE_END(relocate_range);
index 56cdf13611e3d4c05ef5829058de1e0b7804a7ad..78ce1a0a408f5f7cee2fcd6c202d2bf21151e64a 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/orc_lookup.h>
 #include <asm/cache.h>
 #include <asm/boot.h>
+#include <asm/kexec.h>
 
 #undef i386     /* in case the preprocessor is a 32bit one */
 
@@ -95,7 +96,18 @@ const_pcpu_hot = pcpu_hot;
 #define BSS_DECRYPTED
 
 #endif
-
+#if defined(CONFIG_X86_64) && defined(CONFIG_KEXEC_CORE)
+#define KEXEC_RELOCATE_KERNEL                                  \
+       . = ALIGN(0x100);                                       \
+       __relocate_kernel_start = .;                            \
+       *(.text.relocate_kernel);                               \
+       __relocate_kernel_end = .;
+
+ASSERT(__relocate_kernel_end - __relocate_kernel_start <= KEXEC_CONTROL_CODE_MAX_SIZE,
+       "relocate_kernel code too large!")
+#else
+#define KEXEC_RELOCATE_KERNEL
+#endif
 PHDRS {
        text PT_LOAD FLAGS(5);          /* R_E */
        data PT_LOAD FLAGS(6);          /* RW_ */
@@ -184,6 +196,7 @@ SECTIONS
 
                DATA_DATA
                CONSTRUCTORS
+               KEXEC_RELOCATE_KERNEL
 
                /* rarely changed data like cpu maps */
                READ_MOSTLY_DATA(INTERNODE_CACHE_BYTES)