Skip to content

Commit c2cfc23

Browse files
kirylhansendc
authored andcommitted
x86/trampoline: Bypass compat mode in trampoline_start64() if not needed
The trampoline_start64() vector is used when a secondary CPU starts in 64-bit mode. The current implementation directly enters compatibility mode. It is necessary to disable paging and re-enable it in the correct paging mode: either 4- or 5-level, depending on the configuration. The X86S[1] ISA does not support compatibility mode in ring 0, and paging cannot be disabled. Rework the trampoline_start64() function to only enter compatibility mode if it is necessary to change the paging mode. If the CPU is already in the desired paging mode, proceed in long mode. This allows a secondary CPU to boot on an X86S machine as long as the CPU is already in the correct paging mode. In the future, there will be a mechanism to switch between paging modes without disabling paging. [1] https://www.intel.com/content/www/us/en/developer/articles/technical/envisioning-future-simplified-architecture.html [ dhansen: changelog tweaks ] Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Reviewed-by: Andi Kleen <ak@linux.intel.com> Reviewed-by: Kai Huang <kai.huang@intel.com> Link: https://lore.kernel.org/all/20240126100101.689090-1-kirill.shutemov%40linux.intel.com
1 parent 43b1d3e commit c2cfc23

File tree

1 file changed

+32
-1
lines changed

1 file changed

+32
-1
lines changed

arch/x86/realmode/rm/trampoline_64.S

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,15 @@
3737
.text
3838
.code16
3939

40-
.macro LOCK_AND_LOAD_REALMODE_ESP lock_pa=0
40+
.macro LOCK_AND_LOAD_REALMODE_ESP lock_pa=0 lock_rip=0
4141
/*
4242
* Make sure only one CPU fiddles with the realmode stack
4343
*/
4444
.Llock_rm\@:
4545
.if \lock_pa
4646
lock btsl $0, pa_tr_lock
47+
.elseif \lock_rip
48+
lock btsl $0, tr_lock(%rip)
4749
.else
4850
lock btsl $0, tr_lock
4951
.endif
@@ -220,6 +222,35 @@ SYM_CODE_START(trampoline_start64)
220222
lidt tr_idt(%rip)
221223
lgdt tr_gdt64(%rip)
222224

225+
/* Check if paging mode has to be changed */
226+
movq %cr4, %rax
227+
xorl tr_cr4(%rip), %eax
228+
testl $X86_CR4_LA57, %eax
229+
jnz .L_switch_paging
230+
231+
/* Paging mode is correct proceed in 64-bit mode */
232+
233+
LOCK_AND_LOAD_REALMODE_ESP lock_rip=1
234+
235+
movw $__KERNEL_DS, %dx
236+
movl %edx, %ss
237+
addl $pa_real_mode_base, %esp
238+
movl %edx, %ds
239+
movl %edx, %es
240+
movl %edx, %fs
241+
movl %edx, %gs
242+
243+
movl $pa_trampoline_pgd, %eax
244+
movq %rax, %cr3
245+
246+
pushq $__KERNEL_CS
247+
pushq tr_start(%rip)
248+
lretq
249+
.L_switch_paging:
250+
/*
251+
* To switch between 4- and 5-level paging modes, it is necessary
252+
* to disable paging. This must be done in the compatibility mode.
253+
*/
223254
ljmpl *tr_compat(%rip)
224255
SYM_CODE_END(trampoline_start64)
225256

0 commit comments

Comments
 (0)