Skip to content

Commit e27dffb

Browse files
ardbiesheuvelIngo Molnar
authored andcommitted
x86/boot: Move the LA57 trampoline to separate source file
To permit the EFI stub to call this code even when building the kernel without the legacy decompressor, move the trampoline out of the latter's startup code. This is part of an ongoing WIP effort on my part to make the existing, generic EFI zboot format work on x86 as well. No functional change intended. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Link: https://lore.kernel.org/r/20250313120324.1095968-2-ardb+git@google.com
1 parent 558fc8e commit e27dffb

File tree

3 files changed

+113
-103
lines changed

3 files changed

+113
-103
lines changed

arch/x86/boot/compressed/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ ifdef CONFIG_X86_64
9898
vmlinux-objs-$(CONFIG_AMD_MEM_ENCRYPT) += $(obj)/mem_encrypt.o
9999
vmlinux-objs-y += $(obj)/pgtable_64.o
100100
vmlinux-objs-$(CONFIG_AMD_MEM_ENCRYPT) += $(obj)/sev.o
101+
vmlinux-objs-y += $(obj)/la57toggle.o
101102
endif
102103

103104
vmlinux-objs-$(CONFIG_ACPI) += $(obj)/acpi.o

arch/x86/boot/compressed/head_64.S

Lines changed: 0 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -483,110 +483,7 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
483483
jmp *%rax
484484
SYM_FUNC_END(.Lrelocated)
485485

486-
/*
487-
* This is the 32-bit trampoline that will be copied over to low memory. It
488-
* will be called using the ordinary 64-bit calling convention from code
489-
* running in 64-bit mode.
490-
*
491-
* Return address is at the top of the stack (might be above 4G).
492-
* The first argument (EDI) contains the address of the temporary PGD level
493-
* page table in 32-bit addressable memory which will be programmed into
494-
* register CR3.
495-
*/
496-
.section ".rodata", "a", @progbits
497-
SYM_CODE_START(trampoline_32bit_src)
498-
/*
499-
* Preserve callee save 64-bit registers on the stack: this is
500-
* necessary because the architecture does not guarantee that GPRs will
501-
* retain their full 64-bit values across a 32-bit mode switch.
502-
*/
503-
pushq %r15
504-
pushq %r14
505-
pushq %r13
506-
pushq %r12
507-
pushq %rbp
508-
pushq %rbx
509-
510-
/* Preserve top half of RSP in a legacy mode GPR to avoid truncation */
511-
movq %rsp, %rbx
512-
shrq $32, %rbx
513-
514-
/* Switch to compatibility mode (CS.L = 0 CS.D = 1) via far return */
515-
pushq $__KERNEL32_CS
516-
leaq 0f(%rip), %rax
517-
pushq %rax
518-
lretq
519-
520-
/*
521-
* The 32-bit code below will do a far jump back to long mode and end
522-
* up here after reconfiguring the number of paging levels. First, the
523-
* stack pointer needs to be restored to its full 64-bit value before
524-
* the callee save register contents can be popped from the stack.
525-
*/
526-
.Lret:
527-
shlq $32, %rbx
528-
orq %rbx, %rsp
529-
530-
/* Restore the preserved 64-bit registers */
531-
popq %rbx
532-
popq %rbp
533-
popq %r12
534-
popq %r13
535-
popq %r14
536-
popq %r15
537-
retq
538-
539486
.code32
540-
0:
541-
/* Disable paging */
542-
movl %cr0, %eax
543-
btrl $X86_CR0_PG_BIT, %eax
544-
movl %eax, %cr0
545-
546-
/* Point CR3 to the trampoline's new top level page table */
547-
movl %edi, %cr3
548-
549-
/* Set EFER.LME=1 as a precaution in case hypervsior pulls the rug */
550-
movl $MSR_EFER, %ecx
551-
rdmsr
552-
btsl $_EFER_LME, %eax
553-
/* Avoid writing EFER if no change was made (for TDX guest) */
554-
jc 1f
555-
wrmsr
556-
1:
557-
/* Toggle CR4.LA57 */
558-
movl %cr4, %eax
559-
btcl $X86_CR4_LA57_BIT, %eax
560-
movl %eax, %cr4
561-
562-
/* Enable paging again. */
563-
movl %cr0, %eax
564-
btsl $X86_CR0_PG_BIT, %eax
565-
movl %eax, %cr0
566-
567-
/*
568-
* Return to the 64-bit calling code using LJMP rather than LRET, to
569-
* avoid the need for a 32-bit addressable stack. The destination
570-
* address will be adjusted after the template code is copied into a
571-
* 32-bit addressable buffer.
572-
*/
573-
.Ljmp: ljmpl $__KERNEL_CS, $(.Lret - trampoline_32bit_src)
574-
SYM_CODE_END(trampoline_32bit_src)
575-
576-
/*
577-
* This symbol is placed right after trampoline_32bit_src() so its address can
578-
* be used to infer the size of the trampoline code.
579-
*/
580-
SYM_DATA(trampoline_ljmp_imm_offset, .word .Ljmp + 1 - trampoline_32bit_src)
581-
582-
/*
583-
* The trampoline code has a size limit.
584-
* Make sure we fail to compile if the trampoline code grows
585-
* beyond TRAMPOLINE_32BIT_CODE_SIZE bytes.
586-
*/
587-
.org trampoline_32bit_src + TRAMPOLINE_32BIT_CODE_SIZE
588-
589-
.text
590487
SYM_FUNC_START_LOCAL_NOALIGN(.Lno_longmode)
591488
/* This isn't an x86-64 CPU, so hang intentionally, we cannot continue */
592489
1:

arch/x86/boot/compressed/la57toggle.S

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
3+
#include <linux/linkage.h>
4+
#include <asm/segment.h>
5+
#include <asm/boot.h>
6+
#include <asm/msr.h>
7+
#include <asm/processor-flags.h>
8+
#include "pgtable.h"
9+
10+
/*
11+
* This is the 32-bit trampoline that will be copied over to low memory. It
12+
* will be called using the ordinary 64-bit calling convention from code
13+
* running in 64-bit mode.
14+
*
15+
* Return address is at the top of the stack (might be above 4G).
16+
* The first argument (EDI) contains the address of the temporary PGD level
17+
* page table in 32-bit addressable memory which will be programmed into
18+
* register CR3.
19+
*/
20+
21+
.section ".rodata", "a", @progbits
22+
SYM_CODE_START(trampoline_32bit_src)
23+
/*
24+
* Preserve callee save 64-bit registers on the stack: this is
25+
* necessary because the architecture does not guarantee that GPRs will
26+
* retain their full 64-bit values across a 32-bit mode switch.
27+
*/
28+
pushq %r15
29+
pushq %r14
30+
pushq %r13
31+
pushq %r12
32+
pushq %rbp
33+
pushq %rbx
34+
35+
/* Preserve top half of RSP in a legacy mode GPR to avoid truncation */
36+
movq %rsp, %rbx
37+
shrq $32, %rbx
38+
39+
/* Switch to compatibility mode (CS.L = 0 CS.D = 1) via far return */
40+
pushq $__KERNEL32_CS
41+
leaq 0f(%rip), %rax
42+
pushq %rax
43+
lretq
44+
45+
/*
46+
* The 32-bit code below will do a far jump back to long mode and end
47+
* up here after reconfiguring the number of paging levels. First, the
48+
* stack pointer needs to be restored to its full 64-bit value before
49+
* the callee save register contents can be popped from the stack.
50+
*/
51+
.Lret:
52+
shlq $32, %rbx
53+
orq %rbx, %rsp
54+
55+
/* Restore the preserved 64-bit registers */
56+
popq %rbx
57+
popq %rbp
58+
popq %r12
59+
popq %r13
60+
popq %r14
61+
popq %r15
62+
retq
63+
64+
.code32
65+
0:
66+
/* Disable paging */
67+
movl %cr0, %eax
68+
btrl $X86_CR0_PG_BIT, %eax
69+
movl %eax, %cr0
70+
71+
/* Point CR3 to the trampoline's new top level page table */
72+
movl %edi, %cr3
73+
74+
/* Set EFER.LME=1 as a precaution in case hypervsior pulls the rug */
75+
movl $MSR_EFER, %ecx
76+
rdmsr
77+
btsl $_EFER_LME, %eax
78+
/* Avoid writing EFER if no change was made (for TDX guest) */
79+
jc 1f
80+
wrmsr
81+
1:
82+
/* Toggle CR4.LA57 */
83+
movl %cr4, %eax
84+
btcl $X86_CR4_LA57_BIT, %eax
85+
movl %eax, %cr4
86+
87+
/* Enable paging again. */
88+
movl %cr0, %eax
89+
btsl $X86_CR0_PG_BIT, %eax
90+
movl %eax, %cr0
91+
92+
/*
93+
* Return to the 64-bit calling code using LJMP rather than LRET, to
94+
* avoid the need for a 32-bit addressable stack. The destination
95+
* address will be adjusted after the template code is copied into a
96+
* 32-bit addressable buffer.
97+
*/
98+
.Ljmp: ljmpl $__KERNEL_CS, $(.Lret - trampoline_32bit_src)
99+
SYM_CODE_END(trampoline_32bit_src)
100+
101+
/*
102+
* This symbol is placed right after trampoline_32bit_src() so its address can
103+
* be used to infer the size of the trampoline code.
104+
*/
105+
SYM_DATA(trampoline_ljmp_imm_offset, .word .Ljmp + 1 - trampoline_32bit_src)
106+
107+
/*
108+
* The trampoline code has a size limit.
109+
* Make sure we fail to compile if the trampoline code grows
110+
* beyond TRAMPOLINE_32BIT_CODE_SIZE bytes.
111+
*/
112+
.org trampoline_32bit_src + TRAMPOLINE_32BIT_CODE_SIZE

0 commit comments

Comments
 (0)