]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / Ia32 / MpFuncs.nasm
1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR>
3 ; SPDX-License-Identifier: BSD-2-Clause-Patent
4 ;
5 ; Module Name:
6 ;
7 ; MpFuncs.nasm
8 ;
9 ; Abstract:
10 ;
11 ; This is the assembly code for MP support
12 ;
13 ;-------------------------------------------------------------------------------
14
15 %include "MpEqu.inc"
16 extern ASM_PFX(InitializeFloatingPointUnits)
17
18 SECTION .text
19
20 ;-------------------------------------------------------------------------------------
21 ;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
22 ;procedure serializes all the AP processors through an Init sequence. It must be
23 ;noted that APs arrive here very raw...ie: real mode, no stack.
24 ;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
25 ;IS IN MACHINE CODE.
26 ;-------------------------------------------------------------------------------------
27 RendezvousFunnelProcStart:
28 ; At this point CS = 0x(vv00) and ip= 0x0.
29 BITS 16
30 mov ebp, eax ; save BIST information
31
32 mov ax, cs
33 mov ds, ax
34 mov es, ax
35 mov ss, ax
36 xor ax, ax
37 mov fs, ax
38 mov gs, ax
39
40 mov si, MP_CPU_EXCHANGE_INFO_FIELD (BufferStart)
41 mov ebx, [si]
42
43 mov si, MP_CPU_EXCHANGE_INFO_FIELD (DataSegment)
44 mov edx, [si]
45
46 ;
47 ; Get start address of 32-bit code in low memory (<1MB)
48 ;
49 mov edi, MP_CPU_EXCHANGE_INFO_FIELD (ModeTransitionMemory)
50
51 mov si, MP_CPU_EXCHANGE_INFO_FIELD (GdtrProfile)
52 o32 lgdt [cs:si]
53
54 mov si, MP_CPU_EXCHANGE_INFO_FIELD (IdtrProfile)
55 o32 lidt [cs:si]
56
57 ;
58 ; Switch to protected mode
59 ;
60 mov eax, cr0 ; Get control register 0
61 or eax, 000000003h ; Set PE bit (bit #0) & MP
62 mov cr0, eax
63
64 ; Switch to 32-bit code in executable memory (>1MB)
65 o32 jmp far [cs:di]
66
67 ;
68 ; Following code may be copied to memory with type of EfiBootServicesCode.
69 ; This is required at DXE phase if NX is enabled for EfiBootServicesCode of
70 ; memory.
71 ;
72 BITS 32
73 Flat32Start: ; protected mode entry point
74 mov ds, dx
75 mov es, dx
76 mov fs, dx
77 mov gs, dx
78 mov ss, dx
79
80 mov esi, ebx
81
82 mov edi, esi
83 add edi, MP_CPU_EXCHANGE_INFO_FIELD (EnableExecuteDisable)
84 cmp byte [edi], 0
85 jz SkipEnableExecuteDisable
86
87 ;
88 ; Enable IA32 PAE execute disable
89 ;
90
91 mov ecx, 0xc0000080
92 rdmsr
93 bts eax, 11
94 wrmsr
95
96 mov edi, esi
97 add edi, MP_CPU_EXCHANGE_INFO_FIELD (Cr3)
98 mov eax, dword [edi]
99 mov cr3, eax
100
101 mov eax, cr4
102 bts eax, 5
103 mov cr4, eax
104
105 mov eax, cr0
106 bts eax, 31
107 mov cr0, eax
108
109 SkipEnableExecuteDisable:
110 mov edi, esi
111 add edi, MP_CPU_EXCHANGE_INFO_FIELD (InitFlag)
112 cmp dword [edi], 1 ; 1 == ApInitConfig
113 jnz GetApicId
114
115 ; Increment the number of APs executing here as early as possible
116 ; This is decremented in C code when AP is finished executing
117 mov edi, esi
118 add edi, MP_CPU_EXCHANGE_INFO_FIELD (NumApsExecuting)
119 lock inc dword [edi]
120
121 ; AP init
122 mov edi, esi
123 add edi, MP_CPU_EXCHANGE_INFO_FIELD (ApIndex)
124 mov ebx, 1
125 lock xadd dword [edi], ebx ; EBX = ApIndex++
126 inc ebx ; EBX is CpuNumber
127
128 mov edi, esi
129 add edi, MP_CPU_EXCHANGE_INFO_FIELD (StackSize)
130 mov eax, [edi]
131 mov ecx, ebx
132 inc ecx
133 mul ecx ; EAX = StackSize * (CpuNumber + 1)
134 mov edi, esi
135 add edi, MP_CPU_EXCHANGE_INFO_FIELD (StackStart)
136 add eax, [edi]
137 mov esp, eax
138 jmp CProcedureInvoke
139
140 GetApicId:
141 mov eax, 0
142 cpuid
143 cmp eax, 0bh
144 jb NoX2Apic ; CPUID level below CPUID_EXTENDED_TOPOLOGY
145
146 mov eax, 0bh
147 xor ecx, ecx
148 cpuid
149 test ebx, 0ffffh
150 jz NoX2Apic ; CPUID.0BH:EBX[15:0] is zero
151
152 ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX
153 jmp GetProcessorNumber
154
155 NoX2Apic:
156 ; Processor is not x2APIC capable, so get 8-bit APIC ID
157 mov eax, 1
158 cpuid
159 shr ebx, 24
160 mov edx, ebx
161
162 GetProcessorNumber:
163 ;
164 ; Get processor number for this AP
165 ; Note that BSP may become an AP due to SwitchBsp()
166 ;
167 xor ebx, ebx
168 lea eax, [esi + MP_CPU_EXCHANGE_INFO_FIELD (CpuInfo)]
169 mov edi, [eax]
170
171 GetNextProcNumber:
172 cmp dword [edi + CPU_INFO_IN_HOB.InitialApicId], edx ; APIC ID match?
173 jz ProgramStack
174 add edi, CPU_INFO_IN_HOB_size
175 inc ebx
176 jmp GetNextProcNumber
177
178 ProgramStack:
179 mov esp, dword [edi + CPU_INFO_IN_HOB.ApTopOfStack]
180
181 CProcedureInvoke:
182 ;
183 ; Reserve 4 bytes for CpuMpData.
184 ; When the AP wakes up again via INIT-SIPI-SIPI, push 0 will cause the existing CpuMpData to be overwritten with 0.
185 ; CpuMpData is filled in via InitializeApData() during the first time INIT-SIPI-SIPI,
186 ; while overwirrten may occurs when under ApInHltLoop but InitFlag is not set to ApInitConfig.
187 ; Therefore reservation is implemented by sub esp instead of push 0.
188 ;
189 sub esp, 4
190 push ebp ; push BIST data at top of AP stack
191 xor ebp, ebp ; clear ebp for call stack trace
192 push ebp
193 mov ebp, esp
194
195 mov eax, ASM_PFX(InitializeFloatingPointUnits)
196 call eax ; Call assembly function to initialize FPU per UEFI spec
197
198 push ebx ; Push ApIndex
199 mov eax, esi
200 add eax, MP_CPU_EXCHANGE_INFO_OFFSET
201 push eax ; push address of exchange info data buffer
202
203 mov edi, esi
204 add edi, MP_CPU_EXCHANGE_INFO_FIELD (CFunction)
205 mov eax, [edi]
206
207 call eax ; Invoke C function
208
209 jmp $ ; Never reach here
210
211 ;-------------------------------------------------------------------------------------
212 ;SwitchToRealProc procedure follows.
213 ;NOT USED IN 32 BIT MODE.
214 ;-------------------------------------------------------------------------------------
215 SwitchToRealProcStart:
216 jmp $ ; Never reach here
217 SwitchToRealProcEnd:
218
219 RendezvousFunnelProcEnd:
220
221 ;-------------------------------------------------------------------------------------
222 ; AsmRelocateApLoopGeneric (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer);
223 ;
224 ; The last three parameters (Pm16CodeSegment, SevEsAPJumpTable and WakeupBuffer) are
225 ; specific to SEV-ES support and are not applicable on IA32.
226 ;-------------------------------------------------------------------------------------
227 AsmRelocateApLoopGenericStart:
228 mov eax, esp
229 mov esp, [eax + 12] ; TopOfApStack
230 push dword [eax] ; push return address for stack trace
231 push ebp
232 mov ebp, esp
233 mov ebx, [eax + 8] ; ApTargetCState
234 mov ecx, [eax + 4] ; MwaitSupport
235 mov eax, [eax + 16] ; CountTofinish
236 lock dec dword [eax] ; (*CountTofinish)--
237 cmp cl, 1 ; Check mwait-monitor support
238 jnz HltLoopGeneric
239 MwaitLoopGeneric:
240 cli
241 mov eax, esp
242 xor ecx, ecx
243 xor edx, edx
244 monitor
245 mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4]
246 shl eax, 4
247 mwait
248 jmp MwaitLoopGeneric
249 HltLoopGeneric:
250 cli
251 hlt
252 jmp HltLoopGeneric
253 AsmRelocateApLoopGenericEnd:
254
255 ;-------------------------------------------------------------------------------------
256 ; AsmGetAddressMap (&AddressMap);
257 ;-------------------------------------------------------------------------------------
258 global ASM_PFX(AsmGetAddressMap)
259 ASM_PFX(AsmGetAddressMap):
260 pushad
261 mov ebp,esp
262
263 mov ebx, [ebp + 24h]
264 mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RendezvousFunnelAddress], RendezvousFunnelProcStart
265 mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.ModeEntryOffset], Flat32Start - RendezvousFunnelProcStart
266 mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RendezvousFunnelSize], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
267 mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddressGeneric], AsmRelocateApLoopGenericStart
268 mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSizeGeneric], AsmRelocateApLoopGenericEnd - AsmRelocateApLoopGenericStart
269 mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.ModeTransitionOffset], Flat32Start - RendezvousFunnelProcStart
270 mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealNoNxOffset], SwitchToRealProcStart - Flat32Start
271 mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealPM16ModeOffset], 0
272 mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealPM16ModeSize], 0
273
274 popad
275 ret
276
277 ;-------------------------------------------------------------------------------------
278 ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
279 ;about to become an AP. It switches it'stack with the current AP.
280 ;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
281 ;-------------------------------------------------------------------------------------
282 global ASM_PFX(AsmExchangeRole)
283 ASM_PFX(AsmExchangeRole):
284 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
285 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
286 pushad
287 mov ebp,esp
288
289 ; esi contains MyInfo pointer
290 mov esi, [ebp + 24h]
291
292 ; edi contains OthersInfo pointer
293 mov edi, [ebp + 28h]
294
295 ;Store EFLAGS to stack
296 pushfd
297
298 ; Store the its StackPointer
299 mov [esi + CPU_EXCHANGE_ROLE_INFO.StackPointer],esp
300
301 ; update its switch state to STORED
302 mov byte [esi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_STORED
303
304 WaitForOtherStored:
305 ; wait until the other CPU finish storing its state
306 cmp byte [edi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_STORED
307 jz OtherStored
308 pause
309 jmp WaitForOtherStored
310
311 OtherStored:
312 ; load its future StackPointer
313 mov esp, [edi + CPU_EXCHANGE_ROLE_INFO.StackPointer]
314
315 ; update the other CPU's switch state to LOADED
316 mov byte [edi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_LOADED
317
318 WaitForOtherLoaded:
319 ; wait until the other CPU finish loading new state,
320 ; otherwise the data in stack may corrupt
321 cmp byte [esi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_LOADED
322 jz OtherLoaded
323 pause
324 jmp WaitForOtherLoaded
325
326 OtherLoaded:
327 ; since the other CPU already get the data it want, leave this procedure
328 popfd
329
330 popad
331 ret