Skip to content

Commit cb33ff9

Browse files
dwmw2Ingo Molnar
authored andcommitted
x86/kexec: Move relocate_kernel to kernel .data section
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 <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Cc: Baoquan He <[email protected]> Cc: Vivek Goyal <[email protected]> Cc: Dave Young <[email protected]> Cc: Eric Biederman <[email protected]> Cc: Ard Biesheuvel <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent eeebbde commit cb33ff9

File tree

5 files changed

+25
-8
lines changed

5 files changed

+25
-8
lines changed

arch/x86/include/asm/sections.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <asm-generic/sections.h>
66
#include <asm/extable.h>
77

8+
extern char __relocate_kernel_start[], __relocate_kernel_end[];
89
extern char __brk_base[], __brk_limit[];
910
extern char __end_rodata_aligned[];
1011

arch/x86/kernel/callthunks.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,15 @@ static bool skip_addr(void *dest)
139139
return true;
140140
#endif
141141
#ifdef CONFIG_KEXEC_CORE
142+
# ifdef CONFIG_X86_64
143+
if (dest >= (void *)__relocate_kernel_start &&
144+
dest < (void *)__relocate_kernel_end)
145+
return true;
146+
# else
142147
if (dest >= (void *)relocate_kernel &&
143148
dest < (void*)relocate_kernel + KEXEC_CONTROL_CODE_MAX_SIZE)
144149
return true;
150+
# endif
145151
#endif
146152
#ifdef CONFIG_XEN
147153
if (dest >= (void *)hypercall_page &&

arch/x86/kernel/machine_kexec_64.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,14 +307,16 @@ static void load_segments(void)
307307
int machine_kexec_prepare(struct kimage *image)
308308
{
309309
void *control_page = page_address(image->control_code_page);
310+
unsigned long reloc_start = (unsigned long)__relocate_kernel_start;
311+
unsigned long reloc_end = (unsigned long)__relocate_kernel_end;
310312
int result;
311313

312314
/* Setup the identity mapped 64bit page table */
313315
result = init_pgtable(image, __pa(control_page));
314316
if (result)
315317
return result;
316318

317-
__memcpy(control_page, relocate_kernel, KEXEC_CONTROL_CODE_MAX_SIZE);
319+
__memcpy(control_page, __relocate_kernel_start, reloc_end - reloc_start);
318320

319321
set_memory_x((unsigned long)control_page, 1);
320322

arch/x86/kernel/relocate_kernel_64.S

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,8 @@
4141
#define CP_PA_BACKUP_PAGES_MAP DATA(0x30)
4242
#define CP_VA_CONTROL_PAGE DATA(0x38)
4343

44-
.text
45-
.align PAGE_SIZE
44+
.section .text.relocate_kernel,"ax";
4645
.code64
47-
SYM_CODE_START_NOALIGN(relocate_range)
4846
SYM_CODE_START_NOALIGN(relocate_kernel)
4947
UNWIND_HINT_END_OF_STACK
5048
ANNOTATE_NOENDBR
@@ -341,6 +339,3 @@ SYM_CODE_START_LOCAL_NOALIGN(swap_pages)
341339
ret
342340
int3
343341
SYM_CODE_END(swap_pages)
344-
345-
.skip KEXEC_CONTROL_CODE_MAX_SIZE - (. - relocate_kernel), 0xcc
346-
SYM_CODE_END(relocate_range);

arch/x86/kernel/vmlinux.lds.S

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <asm/orc_lookup.h>
2929
#include <asm/cache.h>
3030
#include <asm/boot.h>
31+
#include <asm/kexec.h>
3132

3233
#undef i386 /* in case the preprocessor is a 32bit one */
3334

@@ -95,7 +96,18 @@ const_pcpu_hot = pcpu_hot;
9596
#define BSS_DECRYPTED
9697

9798
#endif
98-
99+
#if defined(CONFIG_X86_64) && defined(CONFIG_KEXEC_CORE)
100+
#define KEXEC_RELOCATE_KERNEL \
101+
. = ALIGN(0x100); \
102+
__relocate_kernel_start = .; \
103+
*(.text.relocate_kernel); \
104+
__relocate_kernel_end = .;
105+
106+
ASSERT(__relocate_kernel_end - __relocate_kernel_start <= KEXEC_CONTROL_CODE_MAX_SIZE,
107+
"relocate_kernel code too large!")
108+
#else
109+
#define KEXEC_RELOCATE_KERNEL
110+
#endif
99111
PHDRS {
100112
text PT_LOAD FLAGS(5); /* R_E */
101113
data PT_LOAD FLAGS(6); /* RW_ */
@@ -184,6 +196,7 @@ SECTIONS
184196

185197
DATA_DATA
186198
CONSTRUCTORS
199+
KEXEC_RELOCATE_KERNEL
187200

188201
/* rarely changed data like cpu maps */
189202
READ_MOSTLY_DATA(INTERNODE_CACHE_BYTES)

0 commit comments

Comments
 (0)