AsmRellocateApLoop() 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.

Cc: Michael Kinney <michael.d.kin...@intel.com>
Cc: Feng Tian <feng.t...@intel.com>
Cc: Giri P Mudusuru <giri.p.mudus...@intel.com>
Cc: Laszlo Ersek <ler...@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <jeff....@intel.com>
---
 UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm | 24 ++++++++++++
 UefiCpuPkg/Library/MpInitLib/MpLib.h           | 21 ++++++++++
 UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm  | 53 ++++++++++++++++++++++++++
 3 files changed, 98 insertions(+)

diff --git a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm 
b/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
index 338c9a2..a289f24 100644
--- a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
+++ b/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
@@ -168,3 +168,27 @@ CProcedureInvoke:
     jmp        $                 ; Never reach here
 RendezvousFunnelProcEnd:
 
+;-------------------------------------------------------------------------------------
+;  AsmRellocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment);
+;-------------------------------------------------------------------------------------
+global ASM_PFX(AsmRellocateApLoop)
+ASM_PFX(AsmRellocateApLoop):
+AsmRellocateApLoopStart:
+    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
+AsmRellocateApLoopEnd:
+
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h 
b/UefiCpuPkg/Library/MpInitLib/MpLib.h
index 28a3cd4..ffa12af 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 mwait-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 mwait-monitor is supported.
+                             FALSE indicates mwait-monitor is not supported.
+  @param[in] ApTargetCState  Target C-State value.
+  @param[in] PmCodeSegment   Proteced mode code segement value.
+**/
+typedef
+VOID
+(EFIAPI * ASM_RELLOCATE_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 b26325f..ff413be 100644
--- a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
+++ b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
@@ -176,3 +176,56 @@ CProcedureInvoke:
 
 RendezvousFunnelProcEnd:
 
+;-------------------------------------------------------------------------------------
+;  AsmRellocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment);
+;-------------------------------------------------------------------------------------
+global ASM_PFX(AsmRellocateApLoop)
+ASM_PFX(AsmRellocateApLoop):
+AsmRellocateApLoopStart:
+    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
+AsmRellocateApLoopEnd:
-- 
2.7.4.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to