]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/CpuMpPei/X64/MpFuncs.nasm
e0a98647dff027360d701cdf87859f4b3569c8f5
[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, LmodeOffsetLocation
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], 0
174 mov qword [rcx + 10h], LongModeStart - RendezvousFunnelProcStart
175 mov qword [rcx + 18h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
176 ret
177
178 ;-------------------------------------------------------------------------------------
179 ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
180 ;about to become an AP. It switches it'stack with the current AP.
181 ;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
182 ;-------------------------------------------------------------------------------------
183 global ASM_PFX(AsmExchangeRole)
184 ASM_PFX(AsmExchangeRole):
185 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
186 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
187
188 push rax
189 push rbx
190 push rcx
191 push rdx
192 push rsi
193 push rdi
194 push rbp
195 push r8
196 push r9
197 push r10
198 push r11
199 push r12
200 push r13
201 push r14
202 push r15
203
204 mov rax, cr0
205 push rax
206
207 mov rax, cr4
208 push rax
209
210 ; rsi contains MyInfo pointer
211 mov rsi, rcx
212
213 ; rdi contains OthersInfo pointer
214 mov rdi, rdx
215
216 ;Store EFLAGS, GDTR and IDTR regiter to stack
217 pushfq
218 sgdt [rsi + 16]
219 sidt [rsi + 26]
220
221 ; Store the its StackPointer
222 mov [rsi + 8], rsp
223
224 ; update its switch state to STORED
225 mov byte [rsi], CPU_SWITCH_STATE_STORED
226
227 WaitForOtherStored:
228 ; wait until the other CPU finish storing its state
229 cmp byte [rdi], CPU_SWITCH_STATE_STORED
230 jz OtherStored
231 pause
232 jmp WaitForOtherStored
233
234 OtherStored:
235 ; Since another CPU already stored its state, load them
236 ; load GDTR value
237 lgdt [rdi + 16]
238
239 ; load IDTR value
240 lidt [rdi + 26]
241
242 ; load its future StackPointer
243 mov rsp, [rdi + 8]
244
245 ; update the other CPU's switch state to LOADED
246 mov byte [rdi], CPU_SWITCH_STATE_LOADED
247
248 WaitForOtherLoaded:
249 ; wait until the other CPU finish loading new state,
250 ; otherwise the data in stack may corrupt
251 cmp byte [rsi], CPU_SWITCH_STATE_LOADED
252 jz OtherLoaded
253 pause
254 jmp WaitForOtherLoaded
255
256 OtherLoaded:
257 ; since the other CPU already get the data it want, leave this procedure
258 popfq
259
260 pop rax
261 mov cr4, rax
262
263 pop rax
264 mov cr0, rax
265
266 pop r15
267 pop r14
268 pop r13
269 pop r12
270 pop r11
271 pop r10
272 pop r9
273 pop r8
274 pop rbp
275 pop rdi
276 pop rsi
277 pop rdx
278 pop rcx
279 pop rbx
280 pop rax
281
282 ret