Skip to content

Commit f6f1ae9

Browse files
KAGA-KOKOPeter Zijlstra
authored andcommitted
x86/smpboot: Implement a bit spinlock to protect the realmode stack
Parallel AP bringup requires that the APs can run fully parallel through the early startup code including the real mode trampoline. To prepare for this implement a bit-spinlock to serialize access to the real mode stack so that parallel upcoming APs are not going to corrupt each others stack while going through the real mode startup code. Co-developed-by: David Woodhouse <[email protected]> Signed-off-by: David Woodhouse <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Tested-by: Michael Kelley <[email protected]> Tested-by: Oleksandr Natalenko <[email protected]> Tested-by: Helge Deller <[email protected]> # parisc Tested-by: Guilherme G. Piccoli <[email protected]> # Steam Deck Link: https://lore.kernel.org/r/[email protected]
1 parent bea629d commit f6f1ae9

File tree

4 files changed

+36
-5
lines changed

4 files changed

+36
-5
lines changed

arch/x86/include/asm/realmode.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ struct trampoline_header {
5252
u64 efer;
5353
u32 cr4;
5454
u32 flags;
55+
u32 lock;
5556
#endif
5657
};
5758

@@ -64,6 +65,8 @@ extern unsigned long initial_stack;
6465
extern unsigned long initial_vc_handler;
6566
#endif
6667

68+
extern u32 *trampoline_lock;
69+
6770
extern unsigned char real_mode_blob[];
6871
extern unsigned char real_mode_relocs[];
6972

arch/x86/kernel/head_64.S

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,16 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL)
251251
movq pcpu_hot + X86_current_task(%rdx), %rax
252252
movq TASK_threadsp(%rax), %rsp
253253

254+
/*
255+
* Now that this CPU is running on its own stack, drop the realmode
256+
* protection. For the boot CPU the pointer is NULL!
257+
*/
258+
movq trampoline_lock(%rip), %rax
259+
testq %rax, %rax
260+
jz .Lsetup_gdt
261+
movl $0, (%rax)
262+
263+
.Lsetup_gdt:
254264
/*
255265
* We must switch to a new descriptor in kernel space for the GDT
256266
* because soon the kernel won't have access anymore to the userspace
@@ -433,6 +443,8 @@ SYM_DATA(initial_code, .quad x86_64_start_kernel)
433443
#ifdef CONFIG_AMD_MEM_ENCRYPT
434444
SYM_DATA(initial_vc_handler, .quad handle_vc_boot_ghcb)
435445
#endif
446+
447+
SYM_DATA(trampoline_lock, .quad 0);
436448
__FINITDATA
437449

438450
__INIT

arch/x86/realmode/init.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ static void __init setup_real_mode(void)
154154

155155
trampoline_header->flags = 0;
156156

157+
trampoline_lock = &trampoline_header->lock;
158+
*trampoline_lock = 0;
159+
157160
trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);
158161

159162
/* Map the real mode stub as virtual == physical */

arch/x86/realmode/rm/trampoline_64.S

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,20 @@
3737
.text
3838
.code16
3939

40+
.macro LOAD_REALMODE_ESP
41+
/*
42+
* Make sure only one CPU fiddles with the realmode stack
43+
*/
44+
.Llock_rm\@:
45+
lock btsl $0, tr_lock
46+
jnc 2f
47+
pause
48+
jmp .Llock_rm\@
49+
2:
50+
# Setup stack
51+
movl $rm_stack_end, %esp
52+
.endm
53+
4054
.balign PAGE_SIZE
4155
SYM_CODE_START(trampoline_start)
4256
cli # We should be safe anyway
@@ -49,8 +63,7 @@ SYM_CODE_START(trampoline_start)
4963
mov %ax, %es
5064
mov %ax, %ss
5165

52-
# Setup stack
53-
movl $rm_stack_end, %esp
66+
LOAD_REALMODE_ESP
5467

5568
call verify_cpu # Verify the cpu supports long mode
5669
testl %eax, %eax # Check for return code
@@ -93,8 +106,7 @@ SYM_CODE_START(sev_es_trampoline_start)
93106
mov %ax, %es
94107
mov %ax, %ss
95108

96-
# Setup stack
97-
movl $rm_stack_end, %esp
109+
LOAD_REALMODE_ESP
98110

99111
jmp .Lswitch_to_protected
100112
SYM_CODE_END(sev_es_trampoline_start)
@@ -177,7 +189,7 @@ SYM_CODE_START(pa_trampoline_compat)
177189
* In compatibility mode. Prep ESP and DX for startup_32, then disable
178190
* paging and complete the switch to legacy 32-bit mode.
179191
*/
180-
movl $rm_stack_end, %esp
192+
LOAD_REALMODE_ESP
181193
movw $__KERNEL_DS, %dx
182194

183195
movl $(CR0_STATE & ~X86_CR0_PG), %eax
@@ -241,6 +253,7 @@ SYM_DATA_START(trampoline_header)
241253
SYM_DATA(tr_efer, .space 8)
242254
SYM_DATA(tr_cr4, .space 4)
243255
SYM_DATA(tr_flags, .space 4)
256+
SYM_DATA(tr_lock, .space 4)
244257
SYM_DATA_END(trampoline_header)
245258

246259
#include "trampoline_common.S"

0 commit comments

Comments
 (0)