summaryrefslogtreecommitdiff
path: root/UefiCpuPkg
diff options
context:
space:
mode:
authorJeff Fan <jeff.fan@intel.com>2016-07-20 22:47:47 +0800
committerJeff Fan <jeff.fan@intel.com>2016-08-17 19:58:56 +0800
commit7615702169b838f9341c312739d29f0795ebd998 (patch)
treeb4a0a7bbd6e822d31422a9dee38a4181e902bc6d /UefiCpuPkg
parent5c66d125eaae51945c0a14ef6d5d3fa2ce7d7a66 (diff)
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>
Diffstat (limited to 'UefiCpuPkg')
-rw-r--r--UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm24
-rw-r--r--UefiCpuPkg/Library/MpInitLib/MpLib.h21
-rw-r--r--UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm54
3 files changed, 99 insertions, 0 deletions
diff --git a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
index 8bacb42836..49f5503530 100644
--- a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
+++ b/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
@@ -169,6 +169,30 @@ CProcedureInvoke:
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);
;-------------------------------------------------------------------------------------
global ASM_PFX(AsmGetAddressMap)
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h
index 28a3cd4b82..39ec5def5b 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.h
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h
@@ -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
diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
index 3c55ffaafe..d5d7efe292 100644
--- a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
+++ b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
@@ -177,6 +177,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);
;-------------------------------------------------------------------------------------
global ASM_PFX(AsmGetAddressMap)