Skip to content

Commit 8282639

Browse files
ardbiesheuvelbp3tk0v
authored andcommitted
x86/startup_64: Simplify virtual switch on primary boot
The secondary startup code is used on the primary boot path as well, but in this case, the initial part runs from a 1:1 mapping, until an explicit cross-jump is made to the kernel virtual mapping of the same code. On the secondary boot path, this jump is pointless as the code already executes from the mapping targeted by the jump. So combine this cross-jump with the jump from startup_64() into the common boot path. This simplifies the execution flow, and clearly separates code that runs from a 1:1 mapping from code that runs from the kernel virtual mapping. Note that this requires a page table switch, so hoist the CR3 assignment into startup_64() as well. And since absolute symbol references will no longer be permitted in .head.text once we enable the associated build time checks, a RIP-relative memory operand is used in the JMP instruction, referring to an absolute constant in the .init.rodata section. Given that the secondary startup code does not require a special placement inside the executable, move it to the .text section. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Tested-by: Tom Lendacky <thomas.lendacky@amd.com> Link: https://lore.kernel.org/r/20240227151907.387873-15-ardb+git@google.com
1 parent d6a41f1 commit 8282639

File tree

1 file changed

+21
-21
lines changed

1 file changed

+21
-21
lines changed

arch/x86/kernel/head_64.S

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ L4_START_KERNEL = l4_index(__START_KERNEL_map)
3939

4040
L3_START_KERNEL = pud_index(__START_KERNEL_map)
4141

42-
.text
4342
__HEAD
4443
.code64
4544
SYM_CODE_START_NOALIGN(startup_64)
@@ -126,9 +125,21 @@ SYM_CODE_START_NOALIGN(startup_64)
126125
call sev_verify_cbit
127126
#endif
128127

129-
jmp 1f
128+
/*
129+
* Switch to early_top_pgt which still has the identity mappings
130+
* present.
131+
*/
132+
movq %rax, %cr3
133+
134+
/* Branch to the common startup code at its kernel virtual address */
135+
ANNOTATE_RETPOLINE_SAFE
136+
jmp *0f(%rip)
130137
SYM_CODE_END(startup_64)
131138

139+
__INITRODATA
140+
0: .quad common_startup_64
141+
142+
.text
132143
SYM_CODE_START(secondary_startup_64)
133144
UNWIND_HINT_END_OF_STACK
134145
ANNOTATE_NOENDBR
@@ -174,8 +185,15 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL)
174185
#ifdef CONFIG_AMD_MEM_ENCRYPT
175186
addq sme_me_mask(%rip), %rax
176187
#endif
188+
/*
189+
* Switch to the init_top_pgt here, away from the trampoline_pgd and
190+
* unmap the identity mapped ranges.
191+
*/
192+
movq %rax, %cr3
177193

178-
1:
194+
SYM_INNER_LABEL(common_startup_64, SYM_L_LOCAL)
195+
UNWIND_HINT_END_OF_STACK
196+
ANNOTATE_NOENDBR
179197

180198
/*
181199
* Create a mask of CR4 bits to preserve. Omit PGE in order to flush
@@ -204,30 +222,12 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL)
204222
btsl $X86_CR4_PSE_BIT, %ecx
205223
movq %rcx, %cr4
206224

207-
/*
208-
* Switch to new page-table
209-
*
210-
* For the boot CPU this switches to early_top_pgt which still has the
211-
* identity mappings present. The secondary CPUs will switch to the
212-
* init_top_pgt here, away from the trampoline_pgd and unmap the
213-
* identity mapped ranges.
214-
*/
215-
movq %rax, %cr3
216-
217225
/*
218226
* Set CR4.PGE to re-enable global translations.
219227
*/
220228
btsl $X86_CR4_PGE_BIT, %ecx
221229
movq %rcx, %cr4
222230

223-
/* Ensure I am executing from virtual addresses */
224-
movq $1f, %rax
225-
ANNOTATE_RETPOLINE_SAFE
226-
jmp *%rax
227-
1:
228-
UNWIND_HINT_END_OF_STACK
229-
ANNOTATE_NOENDBR // above
230-
231231
#ifdef CONFIG_SMP
232232
/*
233233
* For parallel boot, the APIC ID is read from the APIC, and then

0 commit comments

Comments
 (0)