]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/CpuMpPei/X64/MpFuncs.nasm
UefiCpuPkg/CpuMpPei: Consume MpInitLib to produce CPU MP PPI services
[mirror_edk2.git] / UefiCpuPkg / CpuMpPei / X64 / MpFuncs.nasm
1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2015 - 2016, 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 DEFAULT REL
25
26 SECTION .text
27
28 ;-------------------------------------------------------------------------------------
29 ;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
30 ;procedure serializes all the AP processors through an Init sequence. It must be
31 ;noted that APs arrive here very raw...ie: real mode, no stack.
32 ;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
33 ;IS IN MACHINE CODE.
34 ;-------------------------------------------------------------------------------------
35 global ASM_PFX(RendezvousFunnelProc)
36 ASM_PFX(RendezvousFunnelProc):
37 RendezvousFunnelProcStart:
38 ; At this point CS = 0x(vv00) and ip= 0x0.
39 ; Save BIST information to ebp firstly
40
41 BITS 16
42 mov ebp, eax ; Save BIST information
43
44 mov ax, cs
45 mov ds, ax
46 mov es, ax
47 mov ss, ax
48 xor ax, ax
49 mov fs, ax
50 mov gs, ax
51
52 mov si, BufferStartLocation
53 mov ebx, [si]
54
55 mov di, ModeOffsetLocation
56 mov eax, [di]
57 mov di, CodeSegmentLocation
58 mov edx, [di]
59 mov di, ax
60 sub di, 02h
61 mov [di],dx ; Patch long mode CS
62 sub di, 04h
63 add eax, ebx
64 mov [di],eax ; Patch address
65
66 mov si, GdtrLocation
67 o32 lgdt [cs:si]
68
69 mov si, IdtrLocation
70 o32 lidt [cs:si]
71
72
73 mov di, DataSegmentLocation
74 mov edi, [di] ; Save long mode DS in edi
75
76 mov si, Cr3Location ; Save CR3 in ecx
77 mov ecx, [si]
78
79 xor ax, ax
80 mov ds, ax ; Clear data segment
81
82 mov eax, cr0 ; Get control register 0
83 or eax, 000000003h ; Set PE bit (bit #0) & MP
84 mov cr0, eax
85
86 mov eax, cr4
87 bts eax, 5
88 mov cr4, eax
89
90 mov cr3, ecx ; Load CR3
91
92 mov ecx, 0c0000080h ; EFER MSR number
93 rdmsr ; Read EFER
94 bts eax, 8 ; Set LME=1
95 wrmsr ; Write EFER
96
97 mov eax, cr0 ; Read CR0
98 bts eax, 31 ; Set PG=1
99 mov cr0, eax ; Write CR0
100
101 jmp 0:strict dword 0 ; far jump to long mode
102 BITS 64
103 LongModeStart:
104 mov eax, edi
105 mov ds, ax
106 mov es, ax
107 mov ss, ax
108
109 mov esi, ebx
110 mov edi, esi
111 add edi, LockLocation
112 mov rax, NotVacantFlag
113
114 TestLock:
115 xchg qword [edi], rax
116 cmp rax, NotVacantFlag
117 jz TestLock
118
119 mov edi, esi
120 add edi, NumApsExecutingLoction
121 inc dword [edi]
122 mov ebx, [edi]
123
124 ProgramStack:
125 mov edi, esi
126 add edi, StackSizeLocation
127 mov rax, qword [edi]
128 mov edi, esi
129 add edi, StackStartAddressLocation
130 add rax, qword [edi]
131 mov rsp, rax
132 mov qword [edi], rax
133
134 Releaselock:
135 mov rax, VacantFlag
136 mov edi, esi
137 add edi, LockLocation
138 xchg qword [edi], rax
139
140 CProcedureInvoke:
141 push rbp ; push BIST data at top of AP stack
142 xor rbp, rbp ; clear ebp for call stack trace
143 push rbp
144 mov rbp, rsp
145
146 mov rax, ASM_PFX(InitializeFloatingPointUnits)
147 sub rsp, 20h
148 call rax ; Call assembly function to initialize FPU per UEFI spec
149 add rsp, 20h
150
151 mov edx, ebx ; edx is NumApsExecuting
152 mov ecx, esi
153 add ecx, LockLocation ; rcx is address of exchange info data buffer
154
155 mov edi, esi
156 add edi, ApProcedureLocation
157 mov rax, qword [edi]
158
159 sub rsp, 20h
160 call rax ; invoke C function
161 add rsp, 20h
162 jmp $
163
164 RendezvousFunnelProcEnd:
165
166 ;-------------------------------------------------------------------------------------
167 ; AsmGetAddressMap (&AddressMap);
168 ;-------------------------------------------------------------------------------------
169 global ASM_PFX(AsmGetAddressMap)
170 ASM_PFX(AsmGetAddressMap):
171 mov rax, ASM_PFX(RendezvousFunnelProc)
172 mov qword [rcx], rax
173 mov qword [rcx + 8h], LongModeStart - RendezvousFunnelProcStart
174 mov qword [rcx + 10h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
175 ret
176
177 ;-------------------------------------------------------------------------------------
178 ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
179 ;about to become an AP. It switches it'stack with the current AP.
180 ;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
181 ;-------------------------------------------------------------------------------------
182 global ASM_PFX(AsmExchangeRole)
183 ASM_PFX(AsmExchangeRole):
184 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
185 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
186
187 push rax
188 push rbx
189 push rcx
190 push rdx
191 push rsi
192 push rdi
193 push rbp
194 push r8
195 push r9
196 push r10
197 push r11
198 push r12
199 push r13
200 push r14
201 push r15
202
203 mov rax, cr0
204 push rax
205
206 mov rax, cr4
207 push rax
208
209 ; rsi contains MyInfo pointer
210 mov rsi, rcx
211
212 ; rdi contains OthersInfo pointer
213 mov rdi, rdx
214
215 ;Store EFLAGS, GDTR and IDTR regiter to stack
216 pushfq
217 sgdt [rsi + 16]
218 sidt [rsi + 26]
219
220 ; Store the its StackPointer
221 mov [rsi + 8], rsp
222
223 ; update its switch state to STORED
224 mov byte [rsi], CPU_SWITCH_STATE_STORED
225
226 WaitForOtherStored:
227 ; wait until the other CPU finish storing its state
228 cmp byte [rdi], CPU_SWITCH_STATE_STORED
229 jz OtherStored
230 pause
231 jmp WaitForOtherStored
232
233 OtherStored:
234 ; Since another CPU already stored its state, load them
235 ; load GDTR value
236 lgdt [rdi + 16]
237
238 ; load IDTR value
239 lidt [rdi + 26]
240
241 ; load its future StackPointer
242 mov rsp, [rdi + 8]
243
244 ; update the other CPU's switch state to LOADED
245 mov byte [rdi], CPU_SWITCH_STATE_LOADED
246
247 WaitForOtherLoaded:
248 ; wait until the other CPU finish loading new state,
249 ; otherwise the data in stack may corrupt
250 cmp byte [rsi], CPU_SWITCH_STATE_LOADED
251 jz OtherLoaded
252 pause
253 jmp WaitForOtherLoaded
254
255 OtherLoaded:
256 ; since the other CPU already get the data it want, leave this procedure
257 popfq
258
259 pop rax
260 mov cr4, rax
261
262 pop rax
263 mov cr0, rax
264
265 pop r15
266 pop r14
267 pop r13
268 pop r12
269 pop r11
270 pop r10
271 pop r9
272 pop r8
273 pop rbp
274 pop rdi
275 pop rsi
276 pop rdx
277 pop rcx
278 pop rbx
279 pop rax
280
281 ret