Skip to content

Commit 8dbec5c

Browse files
dwmw2Ingo Molnar
authored andcommitted
x86/kexec: Add data section to relocate_kernel
Now that the relocate_kernel page is handled sanely by a linker script we can have actual data, and just use %rip-relative addressing to access it. 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 cb33ff9 commit 8dbec5c

File tree

3 files changed

+38
-33
lines changed

3 files changed

+38
-33
lines changed

arch/x86/kernel/machine_kexec_64.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ void machine_kexec(struct kimage *image)
343343
unsigned long start_address,
344344
unsigned int preserve_context,
345345
unsigned int host_mem_enc_active);
346+
unsigned long reloc_start = (unsigned long)__relocate_kernel_start;
346347
unsigned long page_list[PAGES_NR];
347348
unsigned int host_mem_enc_active;
348349
int save_ftrace_enabled;
@@ -389,7 +390,12 @@ void machine_kexec(struct kimage *image)
389390
page_list[PA_SWAP_PAGE] = (page_to_pfn(image->swap_page)
390391
<< PAGE_SHIFT);
391392

392-
relocate_kernel_ptr = control_page;
393+
/*
394+
* Allow for the possibility that relocate_kernel might not be at
395+
* the very start of the page.
396+
*/
397+
relocate_kernel_ptr = control_page + (unsigned long)relocate_kernel -
398+
reloc_start;
393399

394400
/*
395401
* The segment registers are funny things, they have both a

arch/x86/kernel/relocate_kernel_64.S

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,21 @@
2323
#define PAGE_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
2424

2525
/*
26-
* control_page + KEXEC_CONTROL_CODE_MAX_SIZE
27-
* ~ control_page + PAGE_SIZE are used as data storage and stack for
28-
* jumping back
26+
* The .text.relocate_kernel and .data.relocate_kernel sections are copied
27+
* into the control page, and the remainder of the page is used as the stack.
2928
*/
30-
#define DATA(offset) (KEXEC_CONTROL_CODE_MAX_SIZE+(offset))
3129

30+
.section .data.relocate_kernel,"a";
3231
/* Minimal CPU state */
33-
#define RSP DATA(0x0)
34-
#define CR0 DATA(0x8)
35-
#define CR3 DATA(0x10)
36-
#define CR4 DATA(0x18)
37-
38-
/* other data */
39-
#define CP_PA_TABLE_PAGE DATA(0x20)
40-
#define CP_PA_SWAP_PAGE DATA(0x28)
41-
#define CP_PA_BACKUP_PAGES_MAP DATA(0x30)
42-
#define CP_VA_CONTROL_PAGE DATA(0x38)
32+
SYM_DATA_LOCAL(saved_rsp, .quad 0)
33+
SYM_DATA_LOCAL(saved_cr0, .quad 0)
34+
SYM_DATA_LOCAL(saved_cr3, .quad 0)
35+
SYM_DATA_LOCAL(saved_cr4, .quad 0)
36+
/* other data */
37+
SYM_DATA_LOCAL(va_control_page, .quad 0)
38+
SYM_DATA_LOCAL(pa_table_page, .quad 0)
39+
SYM_DATA_LOCAL(pa_swap_page, .quad 0)
40+
SYM_DATA_LOCAL(pa_backup_pages_map, .quad 0)
4341

4442
.section .text.relocate_kernel,"ax";
4543
.code64
@@ -63,14 +61,13 @@ SYM_CODE_START_NOALIGN(relocate_kernel)
6361
pushq %r15
6462
pushf
6563

66-
movq PTR(VA_CONTROL_PAGE)(%rsi), %r11
67-
movq %rsp, RSP(%r11)
64+
movq %rsp, saved_rsp(%rip)
6865
movq %cr0, %rax
69-
movq %rax, CR0(%r11)
66+
movq %rax, saved_cr0(%rip)
7067
movq %cr3, %rax
71-
movq %rax, CR3(%r11)
68+
movq %rax, saved_cr3(%rip)
7269
movq %cr4, %rax
73-
movq %rax, CR4(%r11)
70+
movq %rax, saved_cr4(%rip)
7471

7572
/* Save CR4. Required to enable the right paging mode later. */
7673
movq %rax, %r13
@@ -83,10 +80,11 @@ SYM_CODE_START_NOALIGN(relocate_kernel)
8380
movq %r8, %r12
8481

8582
/*
86-
* get physical address of control page now
83+
* get physical and virtual address of control page now
8784
* this is impossible after page table switch
8885
*/
8986
movq PTR(PA_CONTROL_PAGE)(%rsi), %r8
87+
movq PTR(VA_CONTROL_PAGE)(%rsi), %r11
9088

9189
/* get physical address of page table now too */
9290
movq PTR(PA_TABLE_PAGE)(%rsi), %r9
@@ -95,10 +93,10 @@ SYM_CODE_START_NOALIGN(relocate_kernel)
9593
movq PTR(PA_SWAP_PAGE)(%rsi), %r10
9694

9795
/* save some information for jumping back */
98-
movq %r9, CP_PA_TABLE_PAGE(%r11)
99-
movq %r10, CP_PA_SWAP_PAGE(%r11)
100-
movq %rdi, CP_PA_BACKUP_PAGES_MAP(%r11)
101-
movq %r11, CP_VA_CONTROL_PAGE(%r11)
96+
movq %r9, pa_table_page(%rip)
97+
movq %r10, pa_swap_page(%rip)
98+
movq %rdi, pa_backup_pages_map(%rip)
99+
movq %r11, va_control_page(%rip)
102100

103101
/* Save the preserve_context to %r11 as swap_pages clobbers %rcx. */
104102
movq %rcx, %r11
@@ -229,13 +227,13 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
229227
/* get the re-entry point of the peer system */
230228
movq 0(%rsp), %rbp
231229
leaq relocate_kernel(%rip), %r8
232-
movq CP_PA_SWAP_PAGE(%r8), %r10
233-
movq CP_PA_BACKUP_PAGES_MAP(%r8), %rdi
234-
movq CP_PA_TABLE_PAGE(%r8), %rax
230+
movq pa_swap_page(%rip), %r10
231+
movq pa_backup_pages_map(%rip), %rdi
232+
movq pa_table_page(%rip), %rax
235233
movq %rax, %cr3
236234
lea PAGE_SIZE(%r8), %rsp
237235
call swap_pages
238-
movq CP_VA_CONTROL_PAGE(%r8), %rax
236+
movq va_control_page(%rip), %rax
239237
addq $(virtual_mapped - relocate_kernel), %rax
240238
pushq %rax
241239
ANNOTATE_UNRET_SAFE
@@ -246,11 +244,11 @@ SYM_CODE_END(identity_mapped)
246244
SYM_CODE_START_LOCAL_NOALIGN(virtual_mapped)
247245
UNWIND_HINT_END_OF_STACK
248246
ANNOTATE_NOENDBR // RET target, above
249-
movq RSP(%r8), %rsp
250-
movq CR4(%r8), %rax
247+
movq saved_rsp(%rip), %rsp
248+
movq saved_cr4(%rip), %rax
251249
movq %rax, %cr4
252-
movq CR3(%r8), %rax
253-
movq CR0(%r8), %r8
250+
movq saved_cr3(%rip), %rax
251+
movq saved_cr0(%rip), %r8
254252
movq %rax, %cr3
255253
movq %r8, %cr0
256254

arch/x86/kernel/vmlinux.lds.S

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ const_pcpu_hot = pcpu_hot;
101101
. = ALIGN(0x100); \
102102
__relocate_kernel_start = .; \
103103
*(.text.relocate_kernel); \
104+
*(.data.relocate_kernel); \
104105
__relocate_kernel_end = .;
105106

106107
ASSERT(__relocate_kernel_end - __relocate_kernel_start <= KEXEC_CONTROL_CODE_MAX_SIZE,

0 commit comments

Comments
 (0)