Skip to content

Commit b3adaba

Browse files
dwmw2Ingo Molnar
authored andcommitted
x86/kexec: Drop page_list argument from relocate_kernel()
The kernel's virtual mapping of the relocate_kernel page currently needs to be RWX because it is written to before the %cr3 switch. Now that the relocate_kernel page has its own .data section and local variables, it can also have *global* variables. So eliminate the separate page_list argument, and write the same information directly to variables in the relocate_kernel page instead. This way, the relocate_kernel code itself doesn't need to copy 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 8dbec5c commit b3adaba

File tree

3 files changed

+24
-42
lines changed

3 files changed

+24
-42
lines changed

arch/x86/include/asm/kexec.h

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,6 @@
88
# define PA_PGD 2
99
# define PA_SWAP_PAGE 3
1010
# define PAGES_NR 4
11-
#else
12-
# define PA_CONTROL_PAGE 0
13-
# define VA_CONTROL_PAGE 1
14-
# define PA_TABLE_PAGE 2
15-
# define PA_SWAP_PAGE 3
16-
# define PAGES_NR 4
1711
#endif
1812

1913
# define KEXEC_CONTROL_PAGE_SIZE 4096
@@ -60,6 +54,10 @@ struct kimage;
6054

6155
/* The native architecture */
6256
# define KEXEC_ARCH KEXEC_ARCH_X86_64
57+
58+
extern unsigned long kexec_va_control_page;
59+
extern unsigned long kexec_pa_table_page;
60+
extern unsigned long kexec_pa_swap_page;
6361
#endif
6462

6563
/*
@@ -122,7 +120,7 @@ relocate_kernel(unsigned long indirection_page,
122120
#else
123121
unsigned long
124122
relocate_kernel(unsigned long indirection_page,
125-
unsigned long page_list,
123+
unsigned long pa_control_page,
126124
unsigned long start_address,
127125
unsigned int preserve_context,
128126
unsigned int host_mem_enc_active);

arch/x86/kernel/machine_kexec_64.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,11 @@ int machine_kexec_prepare(struct kimage *image)
315315
result = init_pgtable(image, __pa(control_page));
316316
if (result)
317317
return result;
318+
kexec_va_control_page = (unsigned long)control_page;
319+
kexec_pa_table_page = (unsigned long)__pa(image->arch.pgd);
320+
321+
if (image->type == KEXEC_TYPE_DEFAULT)
322+
kexec_pa_swap_page = page_to_pfn(image->swap_page) << PAGE_SHIFT;
318323

319324
__memcpy(control_page, __relocate_kernel_start, reloc_end - reloc_start);
320325

@@ -339,12 +344,11 @@ void machine_kexec_cleanup(struct kimage *image)
339344
void machine_kexec(struct kimage *image)
340345
{
341346
unsigned long (*relocate_kernel_ptr)(unsigned long indirection_page,
342-
unsigned long page_list,
347+
unsigned long pa_control_page,
343348
unsigned long start_address,
344349
unsigned int preserve_context,
345350
unsigned int host_mem_enc_active);
346351
unsigned long reloc_start = (unsigned long)__relocate_kernel_start;
347-
unsigned long page_list[PAGES_NR];
348352
unsigned int host_mem_enc_active;
349353
int save_ftrace_enabled;
350354
void *control_page;
@@ -382,14 +386,6 @@ void machine_kexec(struct kimage *image)
382386

383387
control_page = page_address(image->control_code_page);
384388

385-
page_list[PA_CONTROL_PAGE] = virt_to_phys(control_page);
386-
page_list[VA_CONTROL_PAGE] = (unsigned long)control_page;
387-
page_list[PA_TABLE_PAGE] = (unsigned long)__pa(image->arch.pgd);
388-
389-
if (image->type == KEXEC_TYPE_DEFAULT)
390-
page_list[PA_SWAP_PAGE] = (page_to_pfn(image->swap_page)
391-
<< PAGE_SHIFT);
392-
393389
/*
394390
* Allow for the possibility that relocate_kernel might not be at
395391
* the very start of the page.
@@ -417,7 +413,7 @@ void machine_kexec(struct kimage *image)
417413

418414
/* now call it */
419415
image->start = relocate_kernel_ptr((unsigned long)image->head,
420-
(unsigned long)page_list,
416+
virt_to_phys(control_page),
421417
image->start,
422418
image->preserve_context,
423419
host_mem_enc_active);

arch/x86/kernel/relocate_kernel_64.S

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ SYM_DATA_LOCAL(saved_cr0, .quad 0)
3434
SYM_DATA_LOCAL(saved_cr3, .quad 0)
3535
SYM_DATA_LOCAL(saved_cr4, .quad 0)
3636
/* 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)
37+
SYM_DATA(kexec_va_control_page, .quad 0)
38+
SYM_DATA(kexec_pa_table_page, .quad 0)
39+
SYM_DATA(kexec_pa_swap_page, .quad 0)
4040
SYM_DATA_LOCAL(pa_backup_pages_map, .quad 0)
4141

4242
.section .text.relocate_kernel,"ax";
@@ -46,7 +46,7 @@ SYM_CODE_START_NOALIGN(relocate_kernel)
4646
ANNOTATE_NOENDBR
4747
/*
4848
* %rdi indirection_page
49-
* %rsi page_list
49+
* %rsi pa_control_page
5050
* %rdx start address
5151
* %rcx preserve_context
5252
* %r8 host_mem_enc_active
@@ -79,31 +79,19 @@ SYM_CODE_START_NOALIGN(relocate_kernel)
7979
/* Save SME active flag */
8080
movq %r8, %r12
8181

82-
/*
83-
* get physical and virtual address of control page now
84-
* this is impossible after page table switch
85-
*/
86-
movq PTR(PA_CONTROL_PAGE)(%rsi), %r8
87-
movq PTR(VA_CONTROL_PAGE)(%rsi), %r11
88-
89-
/* get physical address of page table now too */
90-
movq PTR(PA_TABLE_PAGE)(%rsi), %r9
91-
92-
/* get physical address of swap page now */
93-
movq PTR(PA_SWAP_PAGE)(%rsi), %r10
94-
95-
/* save some information for jumping back */
96-
movq %r9, pa_table_page(%rip)
97-
movq %r10, pa_swap_page(%rip)
82+
/* save indirection list for jumping back */
9883
movq %rdi, pa_backup_pages_map(%rip)
99-
movq %r11, va_control_page(%rip)
10084

10185
/* Save the preserve_context to %r11 as swap_pages clobbers %rcx. */
10286
movq %rcx, %r11
10387

10488
/* Switch to the identity mapped page tables */
89+
movq kexec_pa_table_page(%rip), %r9
10590
movq %r9, %cr3
10691

92+
/* Physical address of control page */
93+
movq %rsi, %r8
94+
10795
/* setup a new stack at the end of the physical control page */
10896
lea PAGE_SIZE(%r8), %rsp
10997

@@ -227,13 +215,13 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
227215
/* get the re-entry point of the peer system */
228216
movq 0(%rsp), %rbp
229217
leaq relocate_kernel(%rip), %r8
230-
movq pa_swap_page(%rip), %r10
218+
movq kexec_pa_swap_page(%rip), %r10
231219
movq pa_backup_pages_map(%rip), %rdi
232-
movq pa_table_page(%rip), %rax
220+
movq kexec_pa_table_page(%rip), %rax
233221
movq %rax, %cr3
234222
lea PAGE_SIZE(%r8), %rsp
235223
call swap_pages
236-
movq va_control_page(%rip), %rax
224+
movq kexec_va_control_page(%rip), %rax
237225
addq $(virtual_mapped - relocate_kernel), %rax
238226
pushq %rax
239227
ANNOTATE_UNRET_SAFE

0 commit comments

Comments
 (0)