UefiCpuPkg/MpInitLib: split wake up buffer into two parts
If PcdDxeNxMemoryProtectionPolicy is set to enable protection for memory of EfiBootServicesCode, EfiConventionalMemory, the BIOS will hang at a page fault exception during MP initialization. The root cause is that the AP wake up buffer, which is below 1MB and used to hold both AP init code and data, is type of EfiConventionalMemory (not really allocated because of potential conflict with legacy code), and is marked as non-executable. During the transition from real address mode to long mode, the AP init code has to enable paging which will then cause itself a page fault exception because it's just running in non-executable memory. The solution is splitting AP wake up buffer into two part: lower part is still below 1MB and shared with legacy system, higher part is really allocated memory of BootServicesCode type. The init code in the memory below 1MB will not enable paging but just switch to protected mode and jump to higher memory, in which the init code will enable paging and switch to long mode. Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Eric Dong <eric.dong@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Jian J Wang <jian.j.wang@intel.com> Reviewed-by: Eric Dong <eric.dong@intel.com>
This commit is contained in:
@@ -48,34 +48,35 @@ BITS 16
|
||||
mov si, BufferStartLocation
|
||||
mov ebx, [si]
|
||||
|
||||
mov si, ModeOffsetLocation
|
||||
mov eax, [si]
|
||||
mov si, CodeSegmentLocation
|
||||
mov edx, [si]
|
||||
mov di, ax
|
||||
sub di, 02h
|
||||
mov [di], dx
|
||||
sub di, 04h
|
||||
add eax, ebx
|
||||
mov [di],eax
|
||||
|
||||
mov si, DataSegmentLocation
|
||||
mov edx, [si]
|
||||
|
||||
;
|
||||
; Get start address of 32-bit code in low memory (<1MB)
|
||||
;
|
||||
mov edi, ModeTransitionMemoryLocation
|
||||
|
||||
mov si, GdtrLocation
|
||||
o32 lgdt [cs:si]
|
||||
|
||||
mov si, IdtrLocation
|
||||
o32 lidt [cs:si]
|
||||
|
||||
xor ax, ax
|
||||
mov ds, ax
|
||||
|
||||
;
|
||||
; Switch to protected mode
|
||||
;
|
||||
mov eax, cr0 ; Get control register 0
|
||||
or eax, 000000003h ; Set PE bit (bit #0) & MP
|
||||
mov cr0, eax
|
||||
|
||||
jmp 0:strict dword 0 ; far jump to protected mode
|
||||
; Switch to 32-bit code in executable memory (>1MB)
|
||||
o32 jmp far [cs:di]
|
||||
|
||||
;
|
||||
; Following code may be copied to memory with type of EfiBootServicesCode.
|
||||
; This is required at DXE phase if NX is enabled for EfiBootServicesCode of
|
||||
; memory.
|
||||
;
|
||||
BITS 32
|
||||
Flat32Start: ; protected mode entry point
|
||||
mov ds, dx
|
||||
@@ -266,6 +267,7 @@ ASM_PFX(AsmGetAddressMap):
|
||||
mov dword [ebx + 8h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
|
||||
mov dword [ebx + 0Ch], AsmRelocateApLoopStart
|
||||
mov dword [ebx + 10h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
|
||||
mov dword [ebx + 14h], Flat32Start - RendezvousFunnelProcStart
|
||||
|
||||
popad
|
||||
ret
|
||||
|
Reference in New Issue
Block a user