4 Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
22 UINT8 MoveIa32EferMsrToEcx
[5];
23 UINT8 ReadIa32EferMsr
[2];
24 UINT8 SetExecuteDisableBitEnableBit
[4];
25 UINT8 WriteIa32EferMsr
[2];
27 #if defined (MDE_CPU_IA32)
32 UINT8 MoveCr4ToEax
[3];
34 UINT8 MoveEaxToCr4
[3];
36 UINT8 MoveCr0ToEax
[3];
37 UINT8 SetCr0PagingBit
[4];
38 UINT8 MoveEaxToCr0
[3];
40 } ENABLE_EXECUTE_DISABLE_CODE
;
42 ENABLE_EXECUTE_DISABLE_CODE mEnableExecuteDisableCodeTemplate
= {
43 { 0xB9, 0x80, 0x00, 0x00, 0xC0 }, // mov ecx, 0xc0000080
44 { 0x0F, 0x32 }, // rdmsr
45 { 0x0F, 0xBA, 0xE8, 0x0B }, // bts eax, 11
46 { 0x0F, 0x30 }, // wrmsr
48 #if defined (MDE_CPU_IA32)
49 0xB8, 0x00000000, // mov eax, cr3 value
50 { 0x0F, 0x22, 0xd8 }, // mov cr3, eax
52 { 0x0F, 0x20, 0xE0 }, // mov eax, cr4
53 { 0x0F, 0xBA, 0xE8, 0x05 }, // bts eax, 5
54 { 0x0F, 0x22, 0xE0 }, // mov cr4, eax
56 { 0x0F, 0x20, 0xC0 }, // mov eax, cr0
57 { 0x0F, 0xBA, 0xE8, 0x1F }, // bts eax, 31
58 { 0x0F, 0x22, 0xC0 }, // mov cr0, eax
70 UINT8 MovAxRealSegment
; UINT16 RealSegment
;
77 UINT32 MovEaxCr0Value
;
80 UINT8 FarJmp32Flat
[2]; UINT32 FlatJmpOffset
; UINT16 FlatJmpSelector
;
86 UINT32 MovEaxCr4Value
;
89 UINT8 MoveDataSelectorIntoAx
[2]; UINT16 FlatDataSelector
;
90 UINT8 MoveFlatDataSelectorFromAxToDs
[2];
91 UINT8 MoveFlatDataSelectorFromAxToEs
[2];
92 UINT8 MoveFlatDataSelectorFromAxToFs
[2];
93 UINT8 MoveFlatDataSelectorFromAxToGs
[2];
94 UINT8 MoveFlatDataSelectorFromAxToSs
[2];
97 // Code placeholder to enable PAE Execute Disable for IA32
98 // and enable Execute Disable Bit for X64
100 ENABLE_EXECUTE_DISABLE_CODE EnableExecuteDisable
;
102 #if defined (MDE_CPU_X64)
110 UINT8 MoveCr4ToEax
[3];
112 UINT8 MoveEaxToCr4
[3];
114 UINT8 MoveLongModeEnableMsrToEcx
[5];
116 UINT8 SetLongModeEnableBit
[4];
117 UINT8 WriteLmeMsr
[2];
119 UINT8 MoveCr0ToEax
[3];
120 UINT8 SetCr0PagingBit
[4];
121 UINT8 MoveEaxToCr0
[3];
124 UINT8 FarJmp32LongMode
; UINT32 LongJmpOffset
; UINT16 LongJmpSelector
;
125 #endif // defined (MDE_CPU_X64)
127 #if defined (MDE_CPU_X64)
128 UINT8 MovEaxOrRaxCpuDxeEntry
[2]; UINTN CpuDxeEntryValue
;
130 UINT8 MovEaxOrRaxCpuDxeEntry
; UINTN CpuDxeEntryValue
;
132 UINT8 JmpToCpuDxeEntry
[2];
139 This .asm code used for translating processor from 16 bit real mode into
140 64 bit long mode. which help to create the mStartupCodeTemplate value.
143 * nasm -o ApStartup ApStartup.asm
145 * ndisasm -b 16 ApStartup
146 * ndisasm -b 16 -e 6 ApStartup
147 * ndisasm -b 32 -e 32 ApStartup (This -e offset may need adjustment)
148 * ndisasm -b 64 -e 0x83 ApStartup (This -e offset may need adjustment)
150 %define DEFAULT_CR0 0x00000023
151 %define DEFAULT_CR4 0x640
155 jmp short TransitionFromReal16To32BitFlat
166 TransitionFromReal16To32BitFlat:
182 jmp 0x5a5a:dword jumpTo32BitAndLandHere
184 jumpTo32BitAndLandHere:
197 ; Jump to CpuDxe for IA32
201 jz Transition32FlatTo64Flat
207 Transition32FlatTo64Flat:
212 bts eax, 5 ; enable PAE
222 mov cr0, eax ; enable paging
225 ; Jump to CpuDxe for X64
227 jmp 0x5a5a:jumpTo64BitAndLandHere
229 jumpTo64BitAndLandHere:
230 mov rax, 0xcdcdcdcdcdcdcdcd
233 STARTUP_CODE mStartupCodeTemplate
= {
234 { 0xeb, 0x06 }, // Jump to cli
237 0xfa, // cli (Clear Interrupts)
238 0xb8, 0x0000, // mov ax, RealSegment
239 { 0x8e, 0xd8 }, // mov ds, ax
240 { 0xBB, 0x02, 0x00 }, // mov bx, Gdtr
241 { 0x3e, 0x66, 0x0f, 0x01, 0x17 }, // lgdt [ds:bx]
242 { 0x66, 0xB8 }, 0x00000023, // mov eax, cr0 value
243 { 0x0F, 0x22, 0xC0 }, // mov cr0, eax
244 { 0x66, 0xEA }, // far jmp to 32-bit flat
245 OFFSET_OF(STARTUP_CODE
, MovEaxCr4
),
247 0xB8, 0x00000640, // mov eax, cr4 value
248 { 0x0F, 0x22, 0xe0 }, // mov cr4, eax
249 { 0x66, 0xb8 }, CPU_DATA_SEL
, // mov ax, FlatDataSelector
250 { 0x8e, 0xd8 }, // mov ds, ax
251 { 0x8e, 0xc0 }, // mov es, ax
252 { 0x8e, 0xe0 }, // mov fs, ax
253 { 0x8e, 0xe8 }, // mov gs, ax
254 { 0x8e, 0xd0 }, // mov ss, ax
256 #if defined (MDE_CPU_X64)
258 // Code placeholder to enable Execute Disable Bit for X64
259 // Default is all NOP - No Operation
262 { 0x90, 0x90, 0x90, 0x90, 0x90 },
264 { 0x90, 0x90, 0x90, 0x90 },
268 0xB8, 0x00000000, // mov eax, cr3 value
269 { 0x0F, 0x22, 0xd8 }, // mov cr3, eax
271 { 0x0F, 0x20, 0xE0 }, // mov eax, cr4
272 { 0x0F, 0xBA, 0xE8, 0x05 }, // bts eax, 5
273 { 0x0F, 0x22, 0xE0 }, // mov cr4, eax
275 { 0xB9, 0x80, 0x00, 0x00, 0xC0 }, // mov ecx, 0xc0000080
276 { 0x0F, 0x32 }, // rdmsr
277 { 0x0F, 0xBA, 0xE8, 0x08 }, // bts eax, 8
278 { 0x0F, 0x30 }, // wrmsr
280 { 0x0F, 0x20, 0xC0 }, // mov eax, cr0
281 { 0x0F, 0xBA, 0xE8, 0x1F }, // bts eax, 31
282 { 0x0F, 0x22, 0xC0 }, // mov cr0, eax
284 0xEA, // FarJmp32LongMode
285 OFFSET_OF(STARTUP_CODE
, MovEaxOrRaxCpuDxeEntry
),
289 // Code placeholder to enable PAE Execute Disable for IA32
290 // Default is all NOP - No Operation
293 { 0x90, 0x90, 0x90, 0x90, 0x90 },
295 { 0x90, 0x90, 0x90, 0x90 },
299 { 0x90, 0x90, 0x90 },
301 { 0x90, 0x90, 0x90 },
302 { 0x90, 0x90, 0x90, 0x90 },
303 { 0x90, 0x90, 0x90 },
305 { 0x90, 0x90, 0x90 },
306 { 0x90, 0x90, 0x90, 0x90 },
307 { 0x90, 0x90, 0x90 },
311 //0xeb, 0xfe, // jmp $
312 #if defined (MDE_CPU_X64)
313 { 0x48, 0xb8 }, 0x0, // mov rax, X64 CpuDxe MP Entry Point
315 0xB8, 0x0, // mov eax, IA32 CpuDxe MP Entry Point
317 { 0xff, 0xe0 }, // jmp to eax/rax (CpuDxe MP Entry Point)
321 volatile STARTUP_CODE
*StartupCode
= NULL
;
324 The function will check if BSP Execute Disable is enabled.
325 DxeIpl may have enabled Execute Disable for BSP,
326 APs need to get the status and sync up the settings.
328 @retval TRUE BSP Execute Disable is enabled.
329 @retval FALSE BSP Execute Disable is not enabled.
333 IsBspExecuteDisableEnabled (
343 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
344 if (RegEax
>= 0x80000001) {
345 AsmCpuid (0x80000001, NULL
, NULL
, NULL
, &RegEdx
);
348 // Bit 20: Execute Disable Bit available.
350 if ((RegEdx
& BIT20
) != 0) {
351 MsrRegisters
= AsmReadMsr64 (0xC0000080);
354 // Bit 11: Execute Disable Bit enable.
356 if ((MsrRegisters
& BIT11
) != 0) {
366 Prepares Startup Code for APs.
367 This function prepares Startup Code for APs.
369 @retval EFI_SUCCESS The APs were started
370 @retval EFI_OUT_OF_RESOURCES Cannot allocate memory to start APs
374 PrepareAPStartupCode (
379 IA32_DESCRIPTOR Gdtr
;
380 EFI_PHYSICAL_ADDRESS StartAddress
;
382 StartAddress
= BASE_1MB
;
383 Status
= gBS
->AllocatePages (
386 EFI_SIZE_TO_PAGES (sizeof (*StartupCode
)),
389 if (EFI_ERROR (Status
)) {
393 StartupCode
= (STARTUP_CODE
*)(VOID
*)(UINTN
) StartAddress
;
394 CopyMem ((VOID
*) StartupCode
, &mStartupCodeTemplate
, sizeof (*StartupCode
));
395 StartupCode
->RealSegment
= (UINT16
) (((UINTN
) StartAddress
) >> 4);
398 StartupCode
->GdtLimit
= Gdtr
.Limit
;
399 StartupCode
->GdtBase
= (UINT32
) Gdtr
.Base
;
401 StartupCode
->CpuDxeEntryValue
= (UINTN
) AsmApEntryPoint
;
403 StartupCode
->FlatJmpOffset
+= (UINT32
) StartAddress
;
405 if (IsBspExecuteDisableEnabled ()) {
407 (VOID
*) &StartupCode
->EnableExecuteDisable
,
408 &mEnableExecuteDisableCodeTemplate
,
409 sizeof (ENABLE_EXECUTE_DISABLE_CODE
)
412 #if defined (MDE_CPU_X64)
413 StartupCode
->Cr3Value
= (UINT32
) AsmReadCr3 ();
414 StartupCode
->LongJmpOffset
+= (UINT32
) StartAddress
;
416 StartupCode
->EnableExecuteDisable
.Cr3Value
= (UINT32
) AsmReadCr3 ();
423 Free the code buffer of startup AP.
431 if (StartupCode
!= NULL
) {
432 gBS
->FreePages ((EFI_PHYSICAL_ADDRESS
)(UINTN
)(VOID
*) StartupCode
,
433 EFI_SIZE_TO_PAGES (sizeof (*StartupCode
)));
439 Starts the Application Processors and directs them to jump to the
442 The processor jumps to this code in flat mode, but the processor's
443 stack is not initialized.
445 @retval EFI_SUCCESS The APs were started
453 SendInitSipiSipiAllExcludingSelf ((UINT32
)(UINTN
)(VOID
*) StartupCode
);
455 // Wait for APs to arrive at the ApEntryPoint routine
457 MicroSecondDelay (PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds
));
463 Resets the Application Processor and directs it to jump to the
466 The processor jumps to this code in flat mode, but the processor's
467 stack is not initialized.
469 @param ProcessorId the AP of ProcessorId was reset
473 IN UINT32 ProcessorId
476 SendInitSipiSipi (ProcessorId
,
477 (UINT32
)(UINTN
)(VOID
*) StartupCode
);