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 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 si, ModeOffsetLocation 52 mov eax, [si] 53 mov si, CodeSegmentLocation 54 mov edx, [si] 55 mov di, ax 56 sub di, 02h 57 mov [di], dx 58 sub di, 04h 59 add eax, ebx 60 mov [di],eax 61 62 mov si, DataSegmentLocation 63 mov edx, [si] 64 65 mov si, GdtrLocation 66 o32 lgdt [cs:si] 67 68 mov si, IdtrLocation 69 o32 lidt [cs:si] 70 71 xor ax, ax 72 mov ds, ax 73 74 mov eax, cr0 ; Get control register 0 75 or eax, 000000003h ; Set PE bit (bit #0) & MP 76 mov cr0, eax 77 78 jmp 0:strict dword 0 ; far jump to protected mode 79 BITS 32 80 Flat32Start: ; protected mode entry point 81 mov ds, dx 82 mov es, dx 83 mov fs, dx 84 mov gs, dx 85 mov ss, dx 86 87 mov esi, ebx 88 89 mov edi, esi 90 add edi, EnableExecuteDisableLocation 91 cmp byte [edi], 0 92 jz SkipEnableExecuteDisable 93 94 ; 95 ; Enable IA32 PAE execute disable 96 ; 97 98 mov ecx, 0xc0000080 99 rdmsr 100 bts eax, 11 101 wrmsr 102 103 mov edi, esi 104 add edi, Cr3Location 105 mov eax, dword [edi] 106 mov cr3, eax 107 108 mov eax, cr4 109 bts eax, 5 110 mov cr4, eax 111 112 mov eax, cr0 113 bts eax, 31 114 mov cr0, eax 115 116 SkipEnableExecuteDisable: 117 mov edi, esi 118 add edi, InitFlagLocation 119 cmp dword [edi], 1 ; 1 == ApInitConfig 120 jnz GetApicId 121 122 ; AP init 123 mov edi, esi 124 add edi, LockLocation 125 mov eax, NotVacantFlag 126 127 TestLock: 128 xchg [edi], eax 129 cmp eax, NotVacantFlag 130 jz TestLock 131 132 mov ecx, esi 133 add ecx, NumApsExecutingLocation 134 inc dword [ecx] 135 mov ebx, [ecx] 136 137 Releaselock: 138 mov eax, VacantFlag 139 xchg [edi], eax 140 141 mov edi, esi 142 add edi, StackSizeLocation 143 mov eax, [edi] 144 mov ecx, ebx 145 inc ecx 146 mul ecx ; EAX = StackSize * (CpuNumber + 1) 147 mov edi, esi 148 add edi, StackStartAddressLocation 149 add eax, [edi] 150 mov esp, eax 151 jmp CProcedureInvoke 152 153 GetApicId: 154 mov eax, 0 155 cpuid 156 cmp eax, 0bh 157 jb NoX2Apic ; CPUID level below CPUID_EXTENDED_TOPOLOGY 158 159 mov eax, 0bh 160 xor ecx, ecx 161 cpuid 162 test ebx, 0ffffh 163 jz NoX2Apic ; CPUID.0BH:EBX[15:0] is zero 164 165 ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX 166 jmp GetProcessorNumber 167 168 NoX2Apic: 169 ; Processor is not x2APIC capable, so get 8-bit APIC ID 170 mov eax, 1 171 cpuid 172 shr ebx, 24 173 mov edx, ebx 174 175 GetProcessorNumber: 176 ; 177 ; Get processor number for this AP 178 ; Note that BSP may become an AP due to SwitchBsp() 179 ; 180 xor ebx, ebx 181 lea eax, [esi + CpuInfoLocation] 182 mov edi, [eax] 183 184 GetNextProcNumber: 185 cmp [edi], edx ; APIC ID match? 186 jz ProgramStack 187 add edi, 20 188 inc ebx 189 jmp GetNextProcNumber 190 191 ProgramStack: 192 mov esp, [edi + 12] 193 194 CProcedureInvoke: 195 push ebp ; push BIST data at top of AP stack 196 xor ebp, ebp ; clear ebp for call stack trace 197 push ebp 198 mov ebp, esp 199 200 mov eax, ASM_PFX(InitializeFloatingPointUnits) 201 call eax ; Call assembly function to initialize FPU per UEFI spec 202 203 push ebx ; Push NumApsExecuting 204 mov eax, esi 205 add eax, LockLocation 206 push eax ; push address of exchange info data buffer 207 208 mov edi, esi 209 add edi, ApProcedureLocation 210 mov eax, [edi] 211 212 call eax ; Invoke C function 213 214 jmp $ ; Never reach here 215 RendezvousFunnelProcEnd: 216 217 ;------------------------------------------------------------------------------------- 218 ; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish); 219 ;------------------------------------------------------------------------------------- 220 global ASM_PFX(AsmRelocateApLoop) 221 ASM_PFX(AsmRelocateApLoop): 222 AsmRelocateApLoopStart: 223 mov eax, esp 224 mov esp, [eax + 16] ; TopOfApStack 225 push dword [eax] ; push return address for stack trace 226 push ebp 227 mov ebp, esp 228 mov ebx, [eax + 8] ; ApTargetCState 229 mov ecx, [eax + 4] ; MwaitSupport 230 mov eax, [eax + 20] ; CountTofinish 231 lock dec dword [eax] ; (*CountTofinish)-- 232 cmp cl, 1 ; Check mwait-monitor support 233 jnz HltLoop 234 MwaitLoop: 235 mov eax, esp 236 xor ecx, ecx 237 xor edx, edx 238 monitor 239 mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4] 240 shl eax, 4 241 mwait 242 jmp MwaitLoop 243 HltLoop: 244 cli 245 hlt 246 jmp HltLoop 247 AsmRelocateApLoopEnd: 248 249 ;------------------------------------------------------------------------------------- 250 ; AsmGetAddressMap (&AddressMap); 251 ;------------------------------------------------------------------------------------- 252 global ASM_PFX(AsmGetAddressMap) 253 ASM_PFX(AsmGetAddressMap): 254 pushad 255 mov ebp,esp 256 257 mov ebx, [ebp + 24h] 258 mov dword [ebx], RendezvousFunnelProcStart 259 mov dword [ebx + 4h], Flat32Start - RendezvousFunnelProcStart 260 mov dword [ebx + 8h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart 261 mov dword [ebx + 0Ch], AsmRelocateApLoopStart 262 mov dword [ebx + 10h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart 263 264 popad 265 ret 266 267 ;------------------------------------------------------------------------------------- 268 ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is 269 ;about to become an AP. It switches it'stack with the current AP. 270 ;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo); 271 ;------------------------------------------------------------------------------------- 272 global ASM_PFX(AsmExchangeRole) 273 ASM_PFX(AsmExchangeRole): 274 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack 275 ; at the same time. If 1 CPU try to call a function, stack will be corrupted. 276 pushad 277 mov ebp,esp 278 279 ; esi contains MyInfo pointer 280 mov esi, [ebp + 24h] 281 282 ; edi contains OthersInfo pointer 283 mov edi, [ebp + 28h] 284 285 ;Store EFLAGS, GDTR and IDTR register to stack 286 pushfd 287 mov eax, cr4 288 push eax ; push cr4 firstly 289 mov eax, cr0 290 push eax 291 292 sgdt [esi + 8] 293 sidt [esi + 14] 294 295 ; Store the its StackPointer 296 mov [esi + 4],esp 297 298 ; update its switch state to STORED 299 mov byte [esi], CPU_SWITCH_STATE_STORED 300 301 WaitForOtherStored: 302 ; wait until the other CPU finish storing its state 303 cmp byte [edi], CPU_SWITCH_STATE_STORED 304 jz OtherStored 305 pause 306 jmp WaitForOtherStored 307 308 OtherStored: 309 ; Since another CPU already stored its state, load them 310 ; load GDTR value 311 lgdt [edi + 8] 312 313 ; load IDTR value 314 lidt [edi + 14] 315 316 ; load its future StackPointer 317 mov esp, [edi + 4] 318 319 ; update the other CPU's switch state to LOADED 320 mov byte [edi], CPU_SWITCH_STATE_LOADED 321 322 WaitForOtherLoaded: 323 ; wait until the other CPU finish loading new state, 324 ; otherwise the data in stack may corrupt 325 cmp byte [esi], CPU_SWITCH_STATE_LOADED 326 jz OtherLoaded 327 pause 328 jmp WaitForOtherLoaded 329 330 OtherLoaded: 331 ; since the other CPU already get the data it want, leave this procedure 332 pop eax 333 mov cr0, eax 334 pop eax 335 mov cr4, eax 336 popfd 337 338 popad 339 ret 340