]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/CpuMpPei/Ia32/MpFuncs.nasm
UefiCpuPkg/CpuMpPei: Implementation of PeiSwitchBSP ()
[mirror_edk2.git] / UefiCpuPkg / CpuMpPei / Ia32 / MpFuncs.nasm
CommitLineData
f9d30595
JF
1;------------------------------------------------------------------------------ ;
2; Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
3; This program and the accompanying materials
4; are licensed and made available under the terms and conditions of the BSD License
5; which accompanies this distribution. The full text of the license may be found at
6; http://opensource.org/licenses/bsd-license.php.
7;
8; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
10;
11; Module Name:
12;
13; MpFuncs.nasm
14;
15; Abstract:
16;
17; This is the assembly code for MP support
18;
19;-------------------------------------------------------------------------------
20
21%include "MpEqu.inc"
46ba0f63 22extern ASM_PFX(InitializeFloatingPointUnits)
f9d30595
JF
23
24SECTION .text
25
da1475e0
JF
26;-------------------------------------------------------------------------------------
27;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
28;procedure serializes all the AP processors through an Init sequence. It must be
29;noted that APs arrive here very raw...ie: real mode, no stack.
30;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
31;IS IN MACHINE CODE.
32;-------------------------------------------------------------------------------------
33global ASM_PFX(RendezvousFunnelProc)
34ASM_PFX(RendezvousFunnelProc):
35RendezvousFunnelProcStart:
36; At this point CS = 0x(vv00) and ip= 0x0.
37BITS 16
38 mov ebp, eax ; save BIST information
39
40 mov ax, cs
41 mov ds, ax
42 mov es, ax
43 mov ss, ax
44 xor ax, ax
45 mov fs, ax
46 mov gs, ax
47
48 mov si, BufferStartLocation
49 mov ebx, [si]
50
51 mov di, PmodeOffsetLocation
52 mov eax, [di]
53 mov di, ax
54 sub di, 06h
55 add eax, ebx
56 mov [di],eax
57
58 mov si, GdtrLocation
59o32 lgdt [cs:si]
60
61 mov si, IdtrLocation
62o32 lidt [cs:si]
63
64 xor ax, ax
65 mov ds, ax
66
67 mov eax, cr0 ;Get control register 0
68 or eax, 000000003h ;Set PE bit (bit #0) & MP
69 mov cr0, eax
70
71 jmp PROTECT_MODE_CS:strict dword 0 ; far jump to protected mode
72BITS 32
73Flat32Start: ; protected mode entry point
74 mov ax, PROTECT_MODE_DS
75 mov ds, ax
76 mov es, ax
77 mov fs, ax
78 mov gs, ax
79 mov ss, ax
80
81 mov esi, ebx
82 mov edi, esi
83 add edi, LockLocation
84 mov eax, NotVacantFlag
85
86TestLock:
87 xchg [edi], eax
88 cmp eax, NotVacantFlag
89 jz TestLock
90
91 mov edi, esi
92 add edi, NumApsExecutingLoction
93 inc dword [edi]
94 mov ebx, [edi]
95
96ProgramStack:
97 mov edi, esi
98 add edi, StackSizeLocation
99 mov eax, [edi]
100 mov edi, esi
101 add edi, StackStartAddressLocation
102 add eax, [edi]
103 mov esp, eax
104 mov [edi], eax
105
106Releaselock:
107 mov eax, VacantFlag
108 mov edi, esi
109 add edi, LockLocation
110 xchg [edi], eax
111
112CProcedureInvoke:
113 push ebp ; push BIST data at top of AP stack
114 xor ebp, ebp ; clear ebp for call stack trace
115 push ebp
116 mov ebp, esp
117
46ba0f63
JF
118 mov eax, ASM_PFX(InitializeFloatingPointUnits)
119 call eax ; Call assembly function to initialize FPU per UEFI spec
da1475e0
JF
120
121 push ebx ; Push NumApsExecuting
122 mov eax, esi
123 add eax, LockLocation
124 push eax ; push address of exchange info data buffer
125
126 mov edi, esi
127 add edi, ApProcedureLocation
128 mov eax, [edi]
129
130 call eax ; invoke C function
131
132 jmp $ ; never reach here
133RendezvousFunnelProcEnd:
134
8018cb15
JF
135;-------------------------------------------------------------------------------------
136; AsmGetAddressMap (&AddressMap);
137;-------------------------------------------------------------------------------------
138global ASM_PFX(AsmGetAddressMap)
139ASM_PFX(AsmGetAddressMap):
140 pushad
141 mov ebp,esp
142
143 mov ebx, [ebp + 24h]
144 mov dword [ebx], RendezvousFunnelProcStart
145 mov dword [ebx + 4h], Flat32Start - RendezvousFunnelProcStart
146 mov dword [ebx + 8h], 0
147 mov dword [ebx + 0ch], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
148
149 popad
150 ret
f9d30595 151
3798f351
JF
152;-------------------------------------------------------------------------------------
153;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
154;about to become an AP. It switches it'stack with the current AP.
155;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
156;-------------------------------------------------------------------------------------
157global ASM_PFX(AsmExchangeRole)
158ASM_PFX(AsmExchangeRole):
159 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
160 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
161 pushad
162 mov ebp,esp
163
164 ; esi contains MyInfo pointer
165 mov esi, [ebp + 24h]
166
167 ; edi contains OthersInfo pointer
168 mov edi, [ebp + 28h]
169
170 ;Store EFLAGS, GDTR and IDTR register to stack
171 pushfd
172 mov eax, cr4
173 push eax ; push cr4 firstly
174 mov eax, cr0
175 push eax
176
177 sgdt [esi + 8]
178 sidt [esi + 14]
179
180 ; Store the its StackPointer
181 mov [esi + 4],esp
182
183 ; update its switch state to STORED
184 mov byte [esi], CPU_SWITCH_STATE_STORED
185
186WaitForOtherStored:
187 ; wait until the other CPU finish storing its state
188 cmp byte [edi], CPU_SWITCH_STATE_STORED
189 jz OtherStored
190 pause
191 jmp WaitForOtherStored
192
193OtherStored:
194 ; Since another CPU already stored its state, load them
195 ; load GDTR value
196 lgdt [edi + 8]
197
198 ; load IDTR value
199 lidt [edi + 14]
200
201 ; load its future StackPointer
202 mov esp, [edi + 4]
203
204 ; update the other CPU's switch state to LOADED
205 mov byte [edi], CPU_SWITCH_STATE_LOADED
206
207WaitForOtherLoaded:
208 ; wait until the other CPU finish loading new state,
209 ; otherwise the data in stack may corrupt
210 cmp byte [esi], CPU_SWITCH_STATE_LOADED
211 jz OtherLoaded
212 pause
213 jmp WaitForOtherLoaded
214
215OtherLoaded:
216 ; since the other CPU already get the data it want, leave this procedure
217 pop eax
218 mov cr0, eax
219 pop eax
220 mov cr4, eax
221 popfd
222
223 popad
224 ret
225
f9d30595
JF
226global ASM_PFX(AsmInitializeGdt)
227ASM_PFX(AsmInitializeGdt):
228 push ebp
229 mov ebp, esp
230 pushad
231 mov edi, [ebp + 8] ; Load GDT register
232
233 lgdt [edi] ; and update the GDTR
234
235 push PROTECT_MODE_CS
236 mov eax, ASM_PFX(SetCodeSelectorFarJump)
237 push eax
238 retf
239ASM_PFX(SetCodeSelectorFarJump):
240 mov ax, PROTECT_MODE_DS ; Update the Base for the new selectors, too
241 mov ds, ax
242 mov es, ax
243 mov fs, ax
244 mov gs, ax
245 mov ss, ax
246
247 popad
248 pop ebp
249 ret