UefiCpuPkg/MpInitLib: Add AsmRelocateApLoop() assembly code

AsmRelocateApLoop() is used to place APs into MWAIT-loop if MonitorMwait
feature is supported before hand-off to OS, or place APs into HLT-loop if
MonitorMwait feature is not supported.

If the current mode is long mode, we will switch APs to protected mode
before placing APs in MWAIT-loop or HLT-loop. Thus, once APs wakeup from
loop, APs needn't the page table that may be crashed by OS.

v3:
  1. Rename AsmRellocateApLoop to AsmRelocateApLoop.
  2. Fix typo Proteced to Protected.
  3. Fix typo segement to segment
  4. Use word MONITOR instead of mwait-monitor.

Cc: Michael Kinney <michael.d.kinney@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Giri P Mudusuru <giri.p.mudusuru@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <jeff.fan@intel.com>
Reviewed-by: Giri P Mudusuru <giri.p.mudusuru@intel.com>
Reviewed-by: Michael Kinney <michael.d.kinney@intel.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Michael Kinney <michael.d.kinney@intel.com>
This commit is contained in:
Jeff Fan 2016-07-20 22:47:47 +08:00
parent 5c66d125ea
commit 7615702169
3 changed files with 99 additions and 0 deletions

View File

@ -168,6 +168,30 @@ CProcedureInvoke:
jmp $ ; Never reach here
RendezvousFunnelProcEnd:
;-------------------------------------------------------------------------------------
; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment);
;-------------------------------------------------------------------------------------
global ASM_PFX(AsmRelocateApLoop)
ASM_PFX(AsmRelocateApLoop):
AsmRelocateApLoopStart:
cmp byte [esp + 4], 1
jnz HltLoop
MwaitLoop:
mov eax, esp
xor ecx, ecx
xor edx, edx
monitor
mov eax, [esp + 8] ; Mwait Cx, Target C-State per eax[7:4]
shl eax, 4
mwait
jmp MwaitLoop
HltLoop:
cli
hlt
jmp HltLoop
ret
AsmRelocateApLoopEnd:
;-------------------------------------------------------------------------------------
; AsmGetAddressMap (&AddressMap);
;-------------------------------------------------------------------------------------

View File

@ -60,5 +60,26 @@ typedef struct {
} MP_CPU_EXCHANGE_INFO;
#pragma pack()
/**
Assembly code to place AP into safe loop mode.
Place AP into targeted C-State if MONITOR is supported, otherwise
place AP into hlt state.
Place AP in protected mode if the current is long mode. Due to AP maybe
wakeup by some hardware event. It could avoid accessing page table that
may not available during booting to OS.
@param[in] MwaitSupport TRUE indicates MONITOR is supported.
FALSE indicates MONITOR is not supported.
@param[in] ApTargetCState Target C-State value.
@param[in] PmCodeSegment Protected mode code segment value.
**/
typedef
VOID
(EFIAPI * ASM_RELOCATE_AP_LOOP) (
IN BOOLEAN MwaitSupport,
IN UINTN ApTargetCState,
IN UINTN PmCodeSegment
);
#endif

View File

@ -176,6 +176,60 @@ CProcedureInvoke:
RendezvousFunnelProcEnd:
;-------------------------------------------------------------------------------------
; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment);
;-------------------------------------------------------------------------------------
global ASM_PFX(AsmRelocateApLoop)
ASM_PFX(AsmRelocateApLoop):
AsmRelocateApLoopStart:
push rcx
push rdx
lea rsi, [PmEntry] ; rsi <- The start address of transition code
push r8
push rsi
DB 0x48
retf
BITS 32
PmEntry:
mov eax, cr0
btr eax, 31 ; Clear CR0.PG
mov cr0, eax ; Disable paging and caches
mov ebx, edx ; Save EntryPoint to rbx, for rdmsr will overwrite rdx
mov ecx, 0xc0000080
rdmsr
and ah, ~ 1 ; Clear LME
wrmsr
mov eax, cr4
and al, ~ (1 << 5) ; Clear PAE
mov cr4, eax
pop edx
add esp, 4
pop ecx,
add esp, 4
cmp cl, 1 ; Check mwait-monitor support
jnz HltLoop
mov ebx, edx ; Save C-State to ebx
MwaitLoop:
mov eax, esp ; Set Monitor Address
xor ecx, ecx ; ecx = 0
xor edx, edx ; edx = 0
monitor
shl ebx, 4
mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4]
mwait
jmp MwaitLoop
HltLoop:
cli
hlt
jmp HltLoop
ret
BITS 64
AsmRelocateApLoopEnd:
;-------------------------------------------------------------------------------------
; AsmGetAddressMap (&AddressMap);
;-------------------------------------------------------------------------------------