Skip to content

Commit f97b67a

Browse files
ardbiesheuvelbp3tk0v
authored andcommitted
x86/decompressor: Only call the trampoline when changing paging levels
Since the current and desired number of paging levels are known when the trampoline is being prepared, avoid calling the trampoline at all if it is clear that calling it is not going to result in a change to the number of paging levels. Given that the CPU is already running in long mode, the PAE and LA57 settings are necessarily consistent with the currently active page tables, and other fields in CR4 will be initialized by the startup code in the kernel proper. So limit the manipulation of CR4 to toggling the LA57 bit, which is the only thing that really needs doing at this point in the boot. This also means that there is no need to pass the value of l5_required to toggle_la57(), as it will not be called unless CR4.LA57 needs to toggle. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Link: https://lore.kernel.org/r/20230807162720.545787-14-ardb@kernel.org
1 parent 64ef578 commit f97b67a

File tree

2 files changed

+13
-54
lines changed

2 files changed

+13
-54
lines changed

arch/x86/boot/compressed/head_64.S

Lines changed: 4 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -387,10 +387,6 @@ SYM_CODE_START(startup_64)
387387
* For the trampoline, we need the top page table to reside in lower
388388
* memory as we don't have a way to load 64-bit values into CR3 in
389389
* 32-bit mode.
390-
*
391-
* We go though the trampoline even if we don't have to: if we're
392-
* already in a desired paging mode. This way the trampoline code gets
393-
* tested on every boot.
394390
*/
395391

396392
/* Make sure we have GDT with 32-bit code segment */
@@ -526,8 +522,7 @@ SYM_FUNC_END(.Lrelocated)
526522
*
527523
* Return address is at the top of the stack (might be above 4G).
528524
* The first argument (EDI) contains the 32-bit addressable base of the
529-
* trampoline memory. A non-zero second argument (ESI) means that the
530-
* trampoline needs to enable 5-level paging.
525+
* trampoline memory.
531526
*/
532527
.section ".rodata", "a", @progbits
533528
SYM_CODE_START(trampoline_32bit_src)
@@ -579,25 +574,10 @@ SYM_CODE_START(trampoline_32bit_src)
579574
btrl $X86_CR0_PG_BIT, %eax
580575
movl %eax, %cr0
581576

582-
/* Check what paging mode we want to be in after the trampoline */
583-
testl %esi, %esi
584-
jz 1f
585-
586-
/* We want 5-level paging: don't touch CR3 if it already points to 5-level page tables */
587-
movl %cr4, %eax
588-
testl $X86_CR4_LA57, %eax
589-
jnz 3f
590-
jmp 2f
591-
1:
592-
/* We want 4-level paging: don't touch CR3 if it already points to 4-level page tables */
593-
movl %cr4, %eax
594-
testl $X86_CR4_LA57, %eax
595-
jz 3f
596-
2:
597577
/* Point CR3 to the trampoline's new top level page table */
598578
leal TRAMPOLINE_32BIT_PGTABLE_OFFSET(%edi), %eax
599579
movl %eax, %cr3
600-
3:
580+
601581
/* Set EFER.LME=1 as a precaution in case hypervsior pulls the rug */
602582
movl $MSR_EFER, %ecx
603583
rdmsr
@@ -606,26 +586,9 @@ SYM_CODE_START(trampoline_32bit_src)
606586
jc 1f
607587
wrmsr
608588
1:
609-
#ifdef CONFIG_X86_MCE
610-
/*
611-
* Preserve CR4.MCE if the kernel will enable #MC support.
612-
* Clearing MCE may fault in some environments (that also force #MC
613-
* support). Any machine check that occurs before #MC support is fully
614-
* configured will crash the system regardless of the CR4.MCE value set
615-
* here.
616-
*/
589+
/* Toggle CR4.LA57 */
617590
movl %cr4, %eax
618-
andl $X86_CR4_MCE, %eax
619-
#else
620-
movl $0, %eax
621-
#endif
622-
623-
/* Enable PAE and LA57 (if required) paging modes */
624-
orl $X86_CR4_PAE, %eax
625-
testl %esi, %esi
626-
jz 1f
627-
orl $X86_CR4_LA57, %eax
628-
1:
591+
btcl $X86_CR4_LA57_BIT, %eax
629592
movl %eax, %cr4
630593

631594
/* Enable paging again. */

arch/x86/boot/compressed/pgtable_64.c

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ static unsigned long find_trampoline_placement(void)
103103

104104
asmlinkage void configure_5level_paging(struct boot_params *bp)
105105
{
106-
void (*toggle_la57)(void *trampoline, bool enable_5lvl);
106+
void (*toggle_la57)(void *trampoline);
107107
bool l5_required = false;
108108

109109
/* Initialize boot_params. Required for cmdline_find_option_bool(). */
@@ -133,6 +133,13 @@ asmlinkage void configure_5level_paging(struct boot_params *bp)
133133
ptrs_per_p4d = 512;
134134
}
135135

136+
/*
137+
* The trampoline will not be used if the paging mode is already set to
138+
* the desired one.
139+
*/
140+
if (l5_required == !!(native_read_cr4() & X86_CR4_LA57))
141+
return;
142+
136143
trampoline_32bit = (unsigned long *)find_trampoline_placement();
137144

138145
/* Preserve trampoline memory */
@@ -160,18 +167,8 @@ asmlinkage void configure_5level_paging(struct boot_params *bp)
160167
*
161168
* The new page table will be used by trampoline code for switching
162169
* from 4- to 5-level paging or vice versa.
163-
*
164-
* If switching is not required, the page table is unused: trampoline
165-
* code wouldn't touch CR3.
166170
*/
167171

168-
/*
169-
* We are not going to use the page table in trampoline memory if we
170-
* are already in the desired paging mode.
171-
*/
172-
if (l5_required == !!(native_read_cr4() & X86_CR4_LA57))
173-
goto out;
174-
175172
if (l5_required) {
176173
/*
177174
* For 4- to 5-level paging transition, set up current CR3 as
@@ -194,8 +191,7 @@ asmlinkage void configure_5level_paging(struct boot_params *bp)
194191
(void *)src, PAGE_SIZE);
195192
}
196193

197-
out:
198-
toggle_la57(trampoline_32bit, l5_required);
194+
toggle_la57(trampoline_32bit);
199195
}
200196

201197
void cleanup_trampoline(void *pgtable)

0 commit comments

Comments
 (0)