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