]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
MpInitLib: remove unneeded global ASM_PFX
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / X64 / MpFuncs.nasm
CommitLineData
d94e5f67 1;------------------------------------------------------------------------------ ;\r
2aa107c0 2; Copyright (c) 2015 - 2022, Intel Corporation. All rights reserved.<BR>\r
0acd8697 3; SPDX-License-Identifier: BSD-2-Clause-Patent\r
d94e5f67
JF
4;\r
5; Module Name:\r
6;\r
7; MpFuncs.nasm\r
8;\r
9; Abstract:\r
10;\r
11; This is the assembly code for MP support\r
12;\r
13;-------------------------------------------------------------------------------\r
14\r
15%include "MpEqu.inc"\r
16extern ASM_PFX(InitializeFloatingPointUnits)\r
17\r
e2289d19
BS
18%macro OneTimeCall 1\r
19 jmp %1\r
20%1 %+ OneTimerCallReturn:\r
21%endmacro\r
22\r
23%macro OneTimeCallRet 1\r
24 jmp %1 %+ OneTimerCallReturn\r
25%endmacro\r
26\r
d94e5f67
JF
27DEFAULT REL\r
28\r
29SECTION .text\r
30\r
31;-------------------------------------------------------------------------------------\r
32;RendezvousFunnelProc procedure follows. All APs execute their procedure. This\r
33;procedure serializes all the AP processors through an Init sequence. It must be\r
34;noted that APs arrive here very raw...ie: real mode, no stack.\r
35;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC\r
36;IS IN MACHINE CODE.\r
37;-------------------------------------------------------------------------------------\r
d94e5f67
JF
38RendezvousFunnelProcStart:\r
39; At this point CS = 0x(vv00) and ip= 0x0.\r
40; Save BIST information to ebp firstly\r
41\r
42BITS 16\r
43 mov ebp, eax ; Save BIST information\r
44\r
45 mov ax, cs\r
46 mov ds, ax\r
47 mov es, ax\r
48 mov ss, ax\r
49 xor ax, ax\r
50 mov fs, ax\r
51 mov gs, ax\r
52\r
2fba7d4e 53 mov si, MP_CPU_EXCHANGE_INFO_FIELD (BufferStart)\r
d94e5f67
JF
54 mov ebx, [si]\r
55\r
2fba7d4e 56 mov si, MP_CPU_EXCHANGE_INFO_FIELD (DataSegment)\r
f32bfe6d
JW
57 mov edx, [si]\r
58\r
59 ;\r
60 ; Get start address of 32-bit code in low memory (<1MB)\r
61 ;\r
2fba7d4e 62 mov edi, MP_CPU_EXCHANGE_INFO_FIELD (ModeTransitionMemory)\r
d94e5f67 63\r
2fba7d4e 64 mov si, MP_CPU_EXCHANGE_INFO_FIELD (GdtrProfile)\r
d94e5f67
JF
65o32 lgdt [cs:si]\r
66\r
2fba7d4e 67 mov si, MP_CPU_EXCHANGE_INFO_FIELD (IdtrProfile)\r
d94e5f67
JF
68o32 lidt [cs:si]\r
69\r
f32bfe6d
JW
70 ;\r
71 ; Switch to protected mode\r
72 ;\r
73 mov eax, cr0 ; Get control register 0\r
74 or eax, 000000003h ; Set PE bit (bit #0) & MP\r
75 mov cr0, eax\r
76\r
77 ; Switch to 32-bit code (>1MB)\r
78o32 jmp far [cs:di]\r
79\r
80;\r
81; Following code must be copied to memory with type of EfiBootServicesCode.\r
82; This is required if NX is enabled for EfiBootServicesCode of memory.\r
83;\r
84BITS 32\r
85Flat32Start: ; protected mode entry point\r
86 mov ds, dx\r
87 mov es, dx\r
88 mov fs, dx\r
89 mov gs, dx\r
90 mov ss, dx\r
5c66d125
JF
91\r
92 ;\r
93 ; Enable execute disable bit\r
94 ;\r
2fba7d4e 95 mov esi, MP_CPU_EXCHANGE_INFO_FIELD (EnableExecuteDisable)\r
f32bfe6d
JW
96 cmp byte [ebx + esi], 0\r
97 jz SkipEnableExecuteDisableBit\r
98\r
5c66d125
JF
99 mov ecx, 0c0000080h ; EFER MSR number\r
100 rdmsr ; Read EFER\r
101 bts eax, 11 ; Enable Execute Disable Bit\r
102 wrmsr ; Write EFER\r
103\r
104SkipEnableExecuteDisableBit:\r
f32bfe6d
JW
105 ;\r
106 ; Enable PAE\r
107 ;\r
d94e5f67
JF
108 mov eax, cr4\r
109 bts eax, 5\r
09f69a87 110\r
2fba7d4e 111 mov esi, MP_CPU_EXCHANGE_INFO_FIELD (Enable5LevelPaging)\r
09f69a87
RN
112 cmp byte [ebx + esi], 0\r
113 jz SkipEnable5LevelPaging\r
114\r
115 ;\r
116 ; Enable 5 Level Paging\r
117 ;\r
118 bts eax, 12 ; Set LA57=1.\r
119\r
120SkipEnable5LevelPaging:\r
121\r
d94e5f67
JF
122 mov cr4, eax\r
123\r
f32bfe6d
JW
124 ;\r
125 ; Load page table\r
126 ;\r
2fba7d4e 127 mov esi, MP_CPU_EXCHANGE_INFO_FIELD (Cr3) ; Save CR3 in ecx\r
f32bfe6d 128 mov ecx, [ebx + esi]\r
d94e5f67
JF
129 mov cr3, ecx ; Load CR3\r
130\r
f32bfe6d
JW
131 ;\r
132 ; Enable long mode\r
133 ;\r
d94e5f67
JF
134 mov ecx, 0c0000080h ; EFER MSR number\r
135 rdmsr ; Read EFER\r
136 bts eax, 8 ; Set LME=1\r
137 wrmsr ; Write EFER\r
138\r
f32bfe6d
JW
139 ;\r
140 ; Enable paging\r
141 ;\r
d94e5f67
JF
142 mov eax, cr0 ; Read CR0\r
143 bts eax, 31 ; Set PG=1\r
144 mov cr0, eax ; Write CR0\r
145\r
f32bfe6d
JW
146 ;\r
147 ; Far jump to 64-bit code\r
148 ;\r
2fba7d4e 149 mov edi, MP_CPU_EXCHANGE_INFO_FIELD (ModeHighMemory)\r
f32bfe6d
JW
150 add edi, ebx\r
151 jmp far [edi]\r
152\r
d94e5f67 153BITS 64\r
e2289d19
BS
154\r
155;\r
156; Required for the AMD SEV helper functions\r
157;\r
158%include "AmdSev.nasm"\r
159\r
d94e5f67 160LongModeStart:\r
845c5be1 161 mov esi, ebx\r
2fba7d4e 162 lea edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (InitFlag)]\r
845c5be1
JF
163 cmp qword [edi], 1 ; ApInitConfig\r
164 jnz GetApicId\r
165\r
0594ec41
ED
166 ; Increment the number of APs executing here as early as possible\r
167 ; This is decremented in C code when AP is finished executing\r
168 mov edi, esi\r
2fba7d4e 169 add edi, MP_CPU_EXCHANGE_INFO_FIELD (NumApsExecuting)\r
0594ec41
ED
170 lock inc dword [edi]\r
171\r
845c5be1 172 ; AP init\r
62f2cf57 173 mov edi, esi\r
2fba7d4e 174 add edi, MP_CPU_EXCHANGE_INFO_FIELD (ApIndex)\r
62f2cf57
RN
175 mov ebx, 1\r
176 lock xadd dword [edi], ebx ; EBX = ApIndex++\r
177 inc ebx ; EBX is CpuNumber\r
d94e5f67 178\r
845c5be1 179 ; program stack\r
d94e5f67 180 mov edi, esi\r
2fba7d4e 181 add edi, MP_CPU_EXCHANGE_INFO_FIELD (StackSize)\r
845c5be1
JF
182 mov eax, dword [edi]\r
183 mov ecx, ebx\r
184 inc ecx\r
185 mul ecx ; EAX = StackSize * (CpuNumber + 1)\r
d94e5f67 186 mov edi, esi\r
2fba7d4e 187 add edi, MP_CPU_EXCHANGE_INFO_FIELD (StackStart)\r
d94e5f67
JF
188 add rax, qword [edi]\r
189 mov rsp, rax\r
7b7508ad 190\r
7b7508ad 191 ;\r
e2289d19 192 ; Setup the GHCB when AMD SEV-ES active.\r
7b7508ad 193 ;\r
e2289d19 194 OneTimeCall SevEsSetupGhcb\r
845c5be1
JF
195 jmp CProcedureInvoke\r
196\r
197GetApicId:\r
7b7508ad 198 ;\r
e2289d19 199 ; Use the GHCB protocol to get the ApicId when SEV-ES is active.\r
7b7508ad 200 ;\r
e2289d19 201 OneTimeCall SevEsGetApicId\r
7b7508ad
TL
202\r
203DoCpuid:\r
845c5be1
JF
204 mov eax, 0\r
205 cpuid\r
206 cmp eax, 0bh\r
1cbd8330
LE
207 jb NoX2Apic ; CPUID level below CPUID_EXTENDED_TOPOLOGY\r
208\r
209 mov eax, 0bh\r
210 xor ecx, ecx\r
211 cpuid\r
212 test ebx, 0ffffh\r
213 jz NoX2Apic ; CPUID.0BH:EBX[15:0] is zero\r
214\r
215 ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX\r
216 jmp GetProcessorNumber\r
217\r
218NoX2Apic:\r
845c5be1
JF
219 ; Processor is not x2APIC capable, so get 8-bit APIC ID\r
220 mov eax, 1\r
221 cpuid\r
222 shr ebx, 24\r
223 mov edx, ebx\r
845c5be1 224\r
845c5be1
JF
225GetProcessorNumber:\r
226 ;\r
227 ; Get processor number for this AP\r
228 ; Note that BSP may become an AP due to SwitchBsp()\r
229 ;\r
230 xor ebx, ebx\r
2fba7d4e 231 lea eax, [esi + MP_CPU_EXCHANGE_INFO_FIELD (CpuInfo)]\r
edd74ad3 232 mov rdi, [eax]\r
d94e5f67 233\r
845c5be1 234GetNextProcNumber:\r
2fba7d4e 235 cmp dword [rdi + CPU_INFO_IN_HOB.InitialApicId], edx ; APIC ID match?\r
845c5be1 236 jz ProgramStack\r
2fba7d4e 237 add rdi, CPU_INFO_IN_HOB_size\r
845c5be1 238 inc ebx\r
7367cc6c 239 jmp GetNextProcNumber\r
845c5be1
JF
240\r
241ProgramStack:\r
2fba7d4e 242 mov rsp, qword [rdi + CPU_INFO_IN_HOB.ApTopOfStack]\r
d94e5f67
JF
243\r
244CProcedureInvoke:\r
8396e2dd
JF
245 push rbp ; Push BIST data at top of AP stack\r
246 xor rbp, rbp ; Clear ebp for call stack trace\r
d94e5f67
JF
247 push rbp\r
248 mov rbp, rsp\r
249\r
2fba7d4e 250 mov rax, qword [esi + MP_CPU_EXCHANGE_INFO_FIELD (InitializeFloatingPointUnits)]\r
d94e5f67
JF
251 sub rsp, 20h\r
252 call rax ; Call assembly function to initialize FPU per UEFI spec\r
253 add rsp, 20h\r
254\r
37676b9f 255 mov edx, ebx ; edx is ApIndex\r
d94e5f67 256 mov ecx, esi\r
2fba7d4e 257 add ecx, MP_CPU_EXCHANGE_INFO_OFFSET ; rcx is address of exchange info data buffer\r
d94e5f67
JF
258\r
259 mov edi, esi\r
2fba7d4e 260 add edi, MP_CPU_EXCHANGE_INFO_FIELD (CFunction)\r
d94e5f67
JF
261 mov rax, qword [edi]\r
262\r
263 sub rsp, 20h\r
8396e2dd 264 call rax ; Invoke C function\r
d94e5f67 265 add rsp, 20h\r
8396e2dd 266 jmp $ ; Should never reach here\r
d94e5f67
JF
267\r
268RendezvousFunnelProcEnd:\r
269\r
7b7508ad
TL
270;-------------------------------------------------------------------------------------\r
271;SwitchToRealProc procedure follows.\r
272;ALSO THIS PROCEDURE IS EXECUTED BY APs TRANSITIONING TO 16 BIT MODE. HENCE THIS PROC\r
273;IS IN MACHINE CODE.\r
274; SwitchToRealProc (UINTN BufferStart, UINT16 Code16, UINT16 Code32, UINTN StackStart)\r
275; rcx - Buffer Start\r
276; rdx - Code16 Selector Offset\r
277; r8 - Code32 Selector Offset\r
278; r9 - Stack Start\r
279;-------------------------------------------------------------------------------------\r
7b7508ad
TL
280SwitchToRealProcStart:\r
281BITS 64\r
282 cli\r
283\r
284 ;\r
285 ; Get RDX reset value before changing stacks since the\r
286 ; new stack won't be able to accomodate a #VC exception.\r
287 ;\r
288 push rax\r
289 push rbx\r
290 push rcx\r
291 push rdx\r
292\r
293 mov rax, 1\r
294 cpuid\r
295 mov rsi, rax ; Save off the reset value for RDX\r
296\r
297 pop rdx\r
298 pop rcx\r
299 pop rbx\r
300 pop rax\r
301\r
302 ;\r
303 ; Establish stack below 1MB\r
304 ;\r
305 mov rsp, r9\r
306\r
307 ;\r
308 ; Push ultimate Reset Vector onto the stack\r
309 ;\r
310 mov rax, rcx\r
311 shr rax, 4\r
312 push word 0x0002 ; RFLAGS\r
313 push ax ; CS\r
314 push word 0x0000 ; RIP\r
315 push word 0x0000 ; For alignment, will be discarded\r
316\r
317 ;\r
318 ; Get address of "16-bit operand size" label\r
319 ;\r
320 lea rbx, [PM16Mode]\r
321\r
322 ;\r
323 ; Push addresses used to change to compatibility mode\r
324 ;\r
325 lea rax, [CompatMode]\r
326 push r8\r
327 push rax\r
328\r
329 ;\r
330 ; Clear R8 - R15, for reset, before going into 32-bit mode\r
331 ;\r
332 xor r8, r8\r
333 xor r9, r9\r
334 xor r10, r10\r
335 xor r11, r11\r
336 xor r12, r12\r
337 xor r13, r13\r
338 xor r14, r14\r
339 xor r15, r15\r
340\r
341 ;\r
342 ; Far return into 32-bit mode\r
343 ;\r
2aa107c0 344 retfq\r
7b7508ad
TL
345\r
346BITS 32\r
347CompatMode:\r
348 ;\r
349 ; Set up stack to prepare for exiting protected mode\r
350 ;\r
351 push edx ; Code16 CS\r
352 push ebx ; PM16Mode label address\r
353\r
354 ;\r
355 ; Disable paging\r
356 ;\r
357 mov eax, cr0 ; Read CR0\r
358 btr eax, 31 ; Set PG=0\r
359 mov cr0, eax ; Write CR0\r
360\r
361 ;\r
362 ; Disable long mode\r
363 ;\r
364 mov ecx, 0c0000080h ; EFER MSR number\r
365 rdmsr ; Read EFER\r
366 btr eax, 8 ; Set LME=0\r
367 wrmsr ; Write EFER\r
368\r
369 ;\r
370 ; Disable PAE\r
371 ;\r
372 mov eax, cr4 ; Read CR4\r
373 btr eax, 5 ; Set PAE=0\r
374 mov cr4, eax ; Write CR4\r
375\r
376 mov edx, esi ; Restore RDX reset value\r
377\r
378 ;\r
379 ; Switch to 16-bit operand size\r
380 ;\r
381 retf\r
382\r
383BITS 16\r
384 ;\r
385 ; At entry to this label\r
386 ; - RDX will have its reset value\r
387 ; - On the top of the stack\r
388 ; - Alignment data (two bytes) to be discarded\r
389 ; - IP for Real Mode (two bytes)\r
390 ; - CS for Real Mode (two bytes)\r
391 ;\r
20da7ca4
TL
392 ; This label is also used with AsmRelocateApLoop. During MP finalization,\r
393 ; the code from PM16Mode to SwitchToRealProcEnd is copied to the start of\r
394 ; the WakeupBuffer, allowing a parked AP to be booted by an OS.\r
395 ;\r
7b7508ad
TL
396PM16Mode:\r
397 mov eax, cr0 ; Read CR0\r
398 btr eax, 0 ; Set PE=0\r
399 mov cr0, eax ; Write CR0\r
400\r
401 pop ax ; Discard alignment data\r
402\r
403 ;\r
404 ; Clear registers (except RDX and RSP) before going into 16-bit mode\r
405 ;\r
406 xor eax, eax\r
407 xor ebx, ebx\r
408 xor ecx, ecx\r
409 xor esi, esi\r
410 xor edi, edi\r
411 xor ebp, ebp\r
412\r
413 iret\r
414\r
415SwitchToRealProcEnd:\r
416\r
76157021 417;-------------------------------------------------------------------------------------\r
20da7ca4 418; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer);\r
76157021 419;-------------------------------------------------------------------------------------\r
76157021 420AsmRelocateApLoopStart:\r
7b7508ad 421BITS 64\r
20da7ca4
TL
422 cmp qword [rsp + 56], 0 ; SevEsAPJumpTable\r
423 je NoSevEs\r
424\r
425 ;\r
426 ; Perform some SEV-ES related setup before leaving 64-bit mode\r
427 ;\r
428 push rcx\r
429 push rdx\r
430\r
431 ;\r
432 ; Get the RDX reset value using CPUID\r
433 ;\r
434 mov rax, 1\r
435 cpuid\r
436 mov rsi, rax ; Save off the reset value for RDX\r
437\r
438 ;\r
439 ; Prepare the GHCB for the AP_HLT_LOOP VMGEXIT call\r
440 ; - Must be done while in 64-bit long mode so that writes to\r
441 ; the GHCB memory will be unencrypted.\r
442 ; - No NAE events can be generated once this is set otherwise\r
443 ; the AP_RESET_HOLD SW_EXITCODE will be overwritten.\r
444 ;\r
445 mov rcx, 0xc0010130\r
446 rdmsr ; Retrieve current GHCB address\r
447 shl rdx, 32\r
448 or rdx, rax\r
449\r
450 mov rdi, rdx\r
451 xor rax, rax\r
452 mov rcx, 0x800\r
453 shr rcx, 3\r
454 rep stosq ; Clear the GHCB\r
455\r
456 mov rax, 0x80000004 ; VMGEXIT AP_RESET_HOLD\r
457 mov [rdx + 0x390], rax\r
fb2a1a36
TL
458 mov rax, 114 ; Set SwExitCode valid bit\r
459 bts [rdx + 0x3f0], rax\r
460 inc rax ; Set SwExitInfo1 valid bit\r
461 bts [rdx + 0x3f0], rax\r
462 inc rax ; Set SwExitInfo2 valid bit\r
463 bts [rdx + 0x3f0], rax\r
20da7ca4
TL
464\r
465 pop rdx\r
466 pop rcx\r
467\r
468NoSevEs:\r
a7bbe9d2 469 cli ; Disable interrupt before switching to 32-bit mode\r
9f91cb01
JF
470 mov rax, [rsp + 40] ; CountTofinish\r
471 lock dec dword [rax] ; (*CountTofinish)--\r
76157021 472\r
20da7ca4
TL
473 mov r10, [rsp + 48] ; Pm16CodeSegment\r
474 mov rax, [rsp + 56] ; SevEsAPJumpTable\r
475 mov rbx, [rsp + 64] ; WakeupBuffer\r
476 mov rsp, r9 ; TopOfApStack\r
477\r
478 push rax ; Save SevEsAPJumpTable\r
479 push rbx ; Save WakeupBuffer\r
480 push r10 ; Save Pm16CodeSegment\r
481 push rcx ; Save MwaitSupport\r
482 push rdx ; Save ApTargetCState\r
483\r
484 lea rax, [PmEntry] ; rax <- The start address of transition code\r
76157021
JF
485\r
486 push r8\r
20da7ca4
TL
487 push rax\r
488\r
489 ;\r
490 ; Clear R8 - R15, for reset, before going into 32-bit mode\r
491 ;\r
492 xor r8, r8\r
493 xor r9, r9\r
494 xor r10, r10\r
495 xor r11, r11\r
496 xor r12, r12\r
497 xor r13, r13\r
498 xor r14, r14\r
499 xor r15, r15\r
500\r
501 ;\r
502 ; Far return into 32-bit mode\r
503 ;\r
2aa107c0 504 retfq\r
20da7ca4 505\r
76157021
JF
506BITS 32\r
507PmEntry:\r
508 mov eax, cr0\r
509 btr eax, 31 ; Clear CR0.PG\r
510 mov cr0, eax ; Disable paging and caches\r
511\r
76157021
JF
512 mov ecx, 0xc0000080\r
513 rdmsr\r
514 and ah, ~ 1 ; Clear LME\r
515 wrmsr\r
516 mov eax, cr4\r
517 and al, ~ (1 << 5) ; Clear PAE\r
518 mov cr4, eax\r
519\r
520 pop edx\r
521 add esp, 4\r
522 pop ecx,\r
523 add esp, 4\r
20da7ca4
TL
524\r
525MwaitCheck:\r
76157021
JF
526 cmp cl, 1 ; Check mwait-monitor support\r
527 jnz HltLoop\r
528 mov ebx, edx ; Save C-State to ebx\r
529MwaitLoop:\r
a7bbe9d2 530 cli\r
76157021
JF
531 mov eax, esp ; Set Monitor Address\r
532 xor ecx, ecx ; ecx = 0\r
533 xor edx, edx ; edx = 0\r
534 monitor\r
76157021 535 mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4]\r
f56379f3 536 shl eax, 4\r
76157021
JF
537 mwait\r
538 jmp MwaitLoop\r
20da7ca4 539\r
76157021 540HltLoop:\r
20da7ca4
TL
541 pop edx ; PM16CodeSegment\r
542 add esp, 4\r
543 pop ebx ; WakeupBuffer\r
544 add esp, 4\r
545 pop eax ; SevEsAPJumpTable\r
546 add esp, 4\r
547 cmp eax, 0 ; Check for SEV-ES\r
548 je DoHlt\r
549\r
550 cli\r
551 ;\r
552 ; SEV-ES is enabled, use VMGEXIT (GHCB information already\r
553 ; set by caller)\r
554 ;\r
555BITS 64\r
556 rep vmmcall\r
557BITS 32\r
558\r
559 ;\r
560 ; Back from VMGEXIT AP_HLT_LOOP\r
561 ; Push the FLAGS/CS/IP values to use\r
562 ;\r
563 push word 0x0002 ; EFLAGS\r
564 xor ecx, ecx\r
565 mov cx, [eax + 2] ; CS\r
566 push cx\r
567 mov cx, [eax] ; IP\r
568 push cx\r
569 push word 0x0000 ; For alignment, will be discarded\r
570\r
571 push edx\r
572 push ebx\r
573\r
574 mov edx, esi ; Restore RDX reset value\r
575\r
576 retf\r
577\r
578DoHlt:\r
76157021
JF
579 cli\r
580 hlt\r
20da7ca4
TL
581 jmp DoHlt\r
582\r
76157021
JF
583BITS 64\r
584AsmRelocateApLoopEnd:\r
585\r
d94e5f67
JF
586;-------------------------------------------------------------------------------------\r
587; AsmGetAddressMap (&AddressMap);\r
588;-------------------------------------------------------------------------------------\r
589global ASM_PFX(AsmGetAddressMap)\r
590ASM_PFX(AsmGetAddressMap):\r
76323c31 591 lea rax, [RendezvousFunnelProcStart]\r
2fba7d4e
RN
592 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RendezvousFunnelAddress], rax\r
593 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.ModeEntryOffset], LongModeStart - RendezvousFunnelProcStart\r
594 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RendezvousFunnelSize], RendezvousFunnelProcEnd - RendezvousFunnelProcStart\r
76323c31 595 lea rax, [AsmRelocateApLoopStart]\r
2fba7d4e
RN
596 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddress], rax\r
597 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSize], AsmRelocateApLoopEnd - AsmRelocateApLoopStart\r
598 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.ModeTransitionOffset], Flat32Start - RendezvousFunnelProcStart\r
599 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealSize], SwitchToRealProcEnd - SwitchToRealProcStart\r
600 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealOffset], SwitchToRealProcStart - RendezvousFunnelProcStart\r
601 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealNoNxOffset], SwitchToRealProcStart - Flat32Start\r
602 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealPM16ModeOffset], PM16Mode - RendezvousFunnelProcStart\r
603 mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealPM16ModeSize], SwitchToRealProcEnd - PM16Mode\r
d94e5f67
JF
604 ret\r
605\r
606;-------------------------------------------------------------------------------------\r
607;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is\r
8396e2dd 608;about to become an AP. It switches its stack with the current AP.\r
d94e5f67
JF
609;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);\r
610;-------------------------------------------------------------------------------------\r
611global ASM_PFX(AsmExchangeRole)\r
612ASM_PFX(AsmExchangeRole):\r
613 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack\r
614 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.\r
615\r
616 push rax\r
617 push rbx\r
618 push rcx\r
619 push rdx\r
620 push rsi\r
621 push rdi\r
622 push rbp\r
623 push r8\r
624 push r9\r
625 push r10\r
626 push r11\r
627 push r12\r
628 push r13\r
629 push r14\r
630 push r15\r
631\r
632 mov rax, cr0\r
633 push rax\r
634\r
635 mov rax, cr4\r
636 push rax\r
637\r
638 ; rsi contains MyInfo pointer\r
639 mov rsi, rcx\r
640\r
641 ; rdi contains OthersInfo pointer\r
642 mov rdi, rdx\r
643\r
644 ;Store EFLAGS, GDTR and IDTR regiter to stack\r
645 pushfq\r
2fba7d4e
RN
646 sgdt [rsi + CPU_EXCHANGE_ROLE_INFO.Gdtr]\r
647 sidt [rsi + CPU_EXCHANGE_ROLE_INFO.Idtr]\r
d94e5f67
JF
648\r
649 ; Store the its StackPointer\r
2fba7d4e 650 mov [rsi + CPU_EXCHANGE_ROLE_INFO.StackPointer], rsp\r
d94e5f67
JF
651\r
652 ; update its switch state to STORED\r
2fba7d4e 653 mov byte [rsi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_STORED\r
d94e5f67
JF
654\r
655WaitForOtherStored:\r
656 ; wait until the other CPU finish storing its state\r
2fba7d4e 657 cmp byte [rdi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_STORED\r
d94e5f67
JF
658 jz OtherStored\r
659 pause\r
660 jmp WaitForOtherStored\r
661\r
662OtherStored:\r
663 ; Since another CPU already stored its state, load them\r
664 ; load GDTR value\r
2fba7d4e 665 lgdt [rdi + CPU_EXCHANGE_ROLE_INFO.Gdtr]\r
d94e5f67
JF
666\r
667 ; load IDTR value\r
2fba7d4e 668 lidt [rdi + CPU_EXCHANGE_ROLE_INFO.Idtr]\r
d94e5f67
JF
669\r
670 ; load its future StackPointer\r
2fba7d4e 671 mov rsp, [rdi + CPU_EXCHANGE_ROLE_INFO.StackPointer]\r
d94e5f67
JF
672\r
673 ; update the other CPU's switch state to LOADED\r
2fba7d4e 674 mov byte [rdi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_LOADED\r
d94e5f67
JF
675\r
676WaitForOtherLoaded:\r
677 ; wait until the other CPU finish loading new state,\r
678 ; otherwise the data in stack may corrupt\r
2fba7d4e 679 cmp byte [rsi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_LOADED\r
d94e5f67
JF
680 jz OtherLoaded\r
681 pause\r
682 jmp WaitForOtherLoaded\r
683\r
684OtherLoaded:\r
685 ; since the other CPU already get the data it want, leave this procedure\r
686 popfq\r
687\r
688 pop rax\r
689 mov cr4, rax\r
690\r
691 pop rax\r
692 mov cr0, rax\r
693\r
694 pop r15\r
695 pop r14\r
696 pop r13\r
697 pop r12\r
698 pop r11\r
699 pop r10\r
700 pop r9\r
701 pop r8\r
702 pop rbp\r
703 pop rdi\r
704 pop rsi\r
705 pop rdx\r
706 pop rcx\r
707 pop rbx\r
708 pop rax\r
709\r
710 ret\r