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 24DEFAULT REL 25 26SECTION .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;------------------------------------------------------------------------------------- 35global ASM_PFX(RendezvousFunnelProc) 36ASM_PFX(RendezvousFunnelProc): 37RendezvousFunnelProcStart: 38; At this point CS = 0x(vv00) and ip= 0x0. 39; Save BIST information to ebp firstly 40BITS 16 41 42 mov eax, 1234h 43 mov ebp, eax ; save BIST information 44 45 mov ax, cs 46 mov ds, ax 47 mov es, ax 48 mov ss, ax 49 xor ax, ax 50 mov fs, ax 51 mov gs, ax 52 53 mov si, BufferStartLocation 54 mov ebx, [si] 55 56 mov di, PmodeOffsetLocation 57 mov eax, [di] 58 mov di, ax 59 sub di, 06h 60 add eax, ebx 61 mov [di],eax 62 63 mov di, LmodeOffsetLocation 64 mov eax, [di] 65 mov di, ax 66 sub di, 06h 67 add eax, ebx 68 mov [di],eax 69 70 71 mov si, Cr3Location 72 mov ecx,[si] ; ECX is keeping the value of CR3 73 74 mov si, GdtrLocation 75o32 lgdt [cs:si] 76 77 mov si, IdtrLocation 78o32 lidt [cs:si] 79 80 81 xor ax, ax 82 mov ds, ax 83 84 mov eax, cr0 ;Get control register 0 85 or eax, 000000003h ;Set PE bit (bit #0) & MP 86 mov cr0, eax 87 88 jmp PROTECT_MODE_CS:strict dword 0 ; far jump to protected mode 89BITS 32 90Flat32Start: ; protected mode entry point 91 mov ax, PROTECT_MODE_DS 92 mov ds, ax 93 mov es, ax 94 mov fs, ax 95 mov gs, ax 96 mov ss, ax 97 98 mov eax, cr4 99 bts eax, 5 100 mov cr4, eax 101 102 mov cr3, ecx 103 104 105 mov ecx, 0c0000080h ; EFER MSR number. 106 rdmsr ; Read EFER. 107 bts eax, 8 ; Set LME=1. 108 wrmsr ; Write EFER. 109 110 mov eax, cr0 ; Read CR0. 111 bts eax, 31 ; Set PG=1. 112 mov cr0, eax ; Write CR0. 113 114 jmp LONG_MODE_CS:strict dword 0 ; far jump to long mode 115BITS 64 116LongModeStart: 117 mov ax, LONG_MODE_DS 118 mov ds, ax 119 mov es, ax 120 mov ss, ax 121 122 mov esi, ebx 123 mov edi, esi 124 add edi, LockLocation 125 mov rax, NotVacantFlag 126 127TestLock: 128 xchg qword [edi], rax 129 cmp rax, NotVacantFlag 130 jz TestLock 131 132 mov edi, esi 133 add edi, NumApsExecutingLoction 134 inc dword [edi] 135 mov ebx, [edi] 136 137ProgramStack: 138 mov edi, esi 139 add edi, StackSizeLocation 140 mov rax, qword [edi] 141 mov edi, esi 142 add edi, StackStartAddressLocation 143 add rax, qword [edi] 144 mov rsp, rax 145 mov qword [edi], rax 146 147Releaselock: 148 mov rax, VacantFlag 149 mov edi, esi 150 add edi, LockLocation 151 xchg qword [edi], rax 152 153CProcedureInvoke: 154 push rbp ; push BIST data at top of AP stack 155 xor rbp, rbp ; clear ebp for call stack trace 156 push rbp 157 mov rbp, rsp 158 159 mov rax, ASM_PFX(InitializeFloatingPointUnits) 160 sub rsp, 20h 161 call rax ; Call assembly function to initialize FPU per UEFI spec 162 add rsp, 20h 163 164 mov edx, ebx ; edx is NumApsExecuting 165 mov ecx, esi 166 add ecx, LockLocation ; rcx is address of exchange info data buffer 167 168 mov edi, esi 169 add edi, ApProcedureLocation 170 mov rax, qword [edi] 171 172 sub rsp, 20h 173 call rax ; invoke C function 174 add rsp, 20h 175 176RendezvousFunnelProcEnd: 177 178;------------------------------------------------------------------------------------- 179; AsmGetAddressMap (&AddressMap); 180;------------------------------------------------------------------------------------- 181global ASM_PFX(AsmGetAddressMap) 182ASM_PFX(AsmGetAddressMap): 183 mov rax, ASM_PFX(RendezvousFunnelProc) 184 mov qword [rcx], rax 185 mov qword [rcx + 8h], Flat32Start - RendezvousFunnelProcStart 186 mov qword [rcx + 10h], LongModeStart - RendezvousFunnelProcStart 187 mov qword [rcx + 18h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart 188 ret 189 190;------------------------------------------------------------------------------------- 191;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is 192;about to become an AP. It switches it'stack with the current AP. 193;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo); 194;------------------------------------------------------------------------------------- 195global ASM_PFX(AsmExchangeRole) 196ASM_PFX(AsmExchangeRole): 197 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack 198 ; at the same time. If 1 CPU try to call a function, stack will be corrupted. 199 200 push rax 201 push rbx 202 push rcx 203 push rdx 204 push rsi 205 push rdi 206 push rbp 207 push r8 208 push r9 209 push r10 210 push r11 211 push r12 212 push r13 213 push r14 214 push r15 215 216 mov rax, cr0 217 push rax 218 219 mov rax, cr4 220 push rax 221 222 ; rsi contains MyInfo pointer 223 mov rsi, rcx 224 225 ; rdi contains OthersInfo pointer 226 mov rdi, rdx 227 228 ;Store EFLAGS, GDTR and IDTR regiter to stack 229 pushfq 230 sgdt [rsi + 16] 231 sidt [rsi + 26] 232 233 ; Store the its StackPointer 234 mov [rsi + 8], rsp 235 236 ; update its switch state to STORED 237 mov byte [rsi], CPU_SWITCH_STATE_STORED 238 239WaitForOtherStored: 240 ; wait until the other CPU finish storing its state 241 cmp byte [rdi], CPU_SWITCH_STATE_STORED 242 jz OtherStored 243 pause 244 jmp WaitForOtherStored 245 246OtherStored: 247 ; Since another CPU already stored its state, load them 248 ; load GDTR value 249 lgdt [rdi + 16] 250 251 ; load IDTR value 252 lidt [rdi + 26] 253 254 ; load its future StackPointer 255 mov rsp, [rdi + 8] 256 257 ; update the other CPU's switch state to LOADED 258 mov byte [rdi], CPU_SWITCH_STATE_LOADED 259 260WaitForOtherLoaded: 261 ; wait until the other CPU finish loading new state, 262 ; otherwise the data in stack may corrupt 263 cmp byte [rsi], CPU_SWITCH_STATE_LOADED 264 jz OtherLoaded 265 pause 266 jmp WaitForOtherLoaded 267 268OtherLoaded: 269 ; since the other CPU already get the data it want, leave this procedure 270 popfq 271 272 pop rax 273 mov cr4, rax 274 275 pop rax 276 mov cr0, rax 277 278 pop r15 279 pop r14 280 pop r13 281 pop r12 282 pop r11 283 pop r10 284 pop r9 285 pop r8 286 pop rbp 287 pop rdi 288 pop rsi 289 pop rdx 290 pop rcx 291 pop rbx 292 pop rax 293 294 ret 295 296global ASM_PFX(AsmInitializeGdt) 297ASM_PFX(AsmInitializeGdt): 298 push rbp 299 mov rbp, rsp 300 301 lgdt [rcx] ; update the GDTR 302 303 sub rsp, 0x10 304 mov rax, ASM_PFX(SetCodeSelectorFarJump) 305 mov [rsp], rax 306 mov rdx, LONG_MODE_CS 307 mov [rsp + 4], dx ; get new CS 308 jmp far dword [rsp] ; far jump with new CS 309ASM_PFX(SetCodeSelectorFarJump): 310 add rsp, 0x10 311 312 mov rax, LONG_MODE_DS ; get new DS 313 mov ds, ax 314 mov es, ax 315 mov fs, ax 316 mov gs, ax 317 mov ss, ax 318 319 pop rbp 320 321 ret 322