]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/CpuMpPei/Ia32/MpFuncs.nasm
3a8e91fe74ab32792b75298d02254ba954769fb0
[mirror_edk2.git] / UefiCpuPkg / CpuMpPei / Ia32 / MpFuncs.nasm
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"
22 extern ASM_PFX(InitializeFloatingPointUnits)
23
24 SECTION .text
25
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 ;-------------------------------------------------------------------------------------
33 global ASM_PFX(RendezvousFunnelProc)
34 ASM_PFX(RendezvousFunnelProc):
35 RendezvousFunnelProcStart:
36 ; At this point CS = 0x(vv00) and ip= 0x0.
37 BITS 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
59 o32 lgdt [cs:si]
60
61 mov si, IdtrLocation
62 o32 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
72 BITS 32
73 Flat32Start: ; 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
86 TestLock:
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
96 ProgramStack:
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
106 Releaselock:
107 mov eax, VacantFlag
108 mov edi, esi
109 add edi, LockLocation
110 xchg [edi], eax
111
112 CProcedureInvoke:
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
118 mov eax, ASM_PFX(InitializeFloatingPointUnits)
119 call eax ; Call assembly function to initialize FPU per UEFI spec
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
133 RendezvousFunnelProcEnd:
134
135 global ASM_PFX(AsmCliHltLoop)
136 ASM_PFX(AsmCliHltLoop):
137 cli
138 hlt
139 jmp $-2
140
141 ;-------------------------------------------------------------------------------------
142 ; AsmGetAddressMap (&AddressMap);
143 ;-------------------------------------------------------------------------------------
144 global ASM_PFX(AsmGetAddressMap)
145 ASM_PFX(AsmGetAddressMap):
146 pushad
147 mov ebp,esp
148
149 mov ebx, [ebp + 24h]
150 mov dword [ebx], RendezvousFunnelProcStart
151 mov dword [ebx + 4h], Flat32Start - RendezvousFunnelProcStart
152 mov dword [ebx + 8h], 0
153 mov dword [ebx + 0ch], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
154
155 popad
156 ret
157
158 ;-------------------------------------------------------------------------------------
159 ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
160 ;about to become an AP. It switches it'stack with the current AP.
161 ;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
162 ;-------------------------------------------------------------------------------------
163 global ASM_PFX(AsmExchangeRole)
164 ASM_PFX(AsmExchangeRole):
165 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
166 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
167 pushad
168 mov ebp,esp
169
170 ; esi contains MyInfo pointer
171 mov esi, [ebp + 24h]
172
173 ; edi contains OthersInfo pointer
174 mov edi, [ebp + 28h]
175
176 ;Store EFLAGS, GDTR and IDTR register to stack
177 pushfd
178 mov eax, cr4
179 push eax ; push cr4 firstly
180 mov eax, cr0
181 push eax
182
183 sgdt [esi + 8]
184 sidt [esi + 14]
185
186 ; Store the its StackPointer
187 mov [esi + 4],esp
188
189 ; update its switch state to STORED
190 mov byte [esi], CPU_SWITCH_STATE_STORED
191
192 WaitForOtherStored:
193 ; wait until the other CPU finish storing its state
194 cmp byte [edi], CPU_SWITCH_STATE_STORED
195 jz OtherStored
196 pause
197 jmp WaitForOtherStored
198
199 OtherStored:
200 ; Since another CPU already stored its state, load them
201 ; load GDTR value
202 lgdt [edi + 8]
203
204 ; load IDTR value
205 lidt [edi + 14]
206
207 ; load its future StackPointer
208 mov esp, [edi + 4]
209
210 ; update the other CPU's switch state to LOADED
211 mov byte [edi], CPU_SWITCH_STATE_LOADED
212
213 WaitForOtherLoaded:
214 ; wait until the other CPU finish loading new state,
215 ; otherwise the data in stack may corrupt
216 cmp byte [esi], CPU_SWITCH_STATE_LOADED
217 jz OtherLoaded
218 pause
219 jmp WaitForOtherLoaded
220
221 OtherLoaded:
222 ; since the other CPU already get the data it want, leave this procedure
223 pop eax
224 mov cr0, eax
225 pop eax
226 mov cr4, eax
227 popfd
228
229 popad
230 ret
231
232 global ASM_PFX(AsmInitializeGdt)
233 ASM_PFX(AsmInitializeGdt):
234 push ebp
235 mov ebp, esp
236 pushad
237 mov edi, [ebp + 8] ; Load GDT register
238
239 lgdt [edi] ; and update the GDTR
240
241 push PROTECT_MODE_CS
242 mov eax, ASM_PFX(SetCodeSelectorFarJump)
243 push eax
244 retf
245 ASM_PFX(SetCodeSelectorFarJump):
246 mov ax, PROTECT_MODE_DS ; Update the Base for the new selectors, too
247 mov ds, ax
248 mov es, ax
249 mov fs, ax
250 mov gs, ax
251 mov ss, ax
252
253 popad
254 pop ebp
255 ret