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