]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg/MpInitLib: Add AsmRelocateApLoop() assembly code
authorJeff Fan <jeff.fan@intel.com>
Wed, 20 Jul 2016 14:47:47 +0000 (22:47 +0800)
committerJeff Fan <jeff.fan@intel.com>
Wed, 17 Aug 2016 11:58:56 +0000 (19:58 +0800)
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>
UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
UefiCpuPkg/Library/MpInitLib/MpLib.h
UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm

index 8bacb4283641370eab2be4d83a8e9894fe649cdf..49f55035309643d38a548896332126ec3a03c59c 100644 (file)
@@ -168,6 +168,30 @@ CProcedureInvoke:
     jmp        $                 ; Never reach here\r
 RendezvousFunnelProcEnd:\r
 \r
+;-------------------------------------------------------------------------------------\r
+;  AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment);\r
+;-------------------------------------------------------------------------------------\r
+global ASM_PFX(AsmRelocateApLoop)\r
+ASM_PFX(AsmRelocateApLoop):\r
+AsmRelocateApLoopStart:\r
+    cmp        byte [esp + 4], 1\r
+    jnz        HltLoop\r
+MwaitLoop:\r
+    mov        eax, esp\r
+    xor        ecx, ecx\r
+    xor        edx, edx\r
+    monitor\r
+    mov        eax, [esp + 8]    ; Mwait Cx, Target C-State per eax[7:4]\r
+    shl        eax, 4\r
+    mwait\r
+    jmp        MwaitLoop\r
+HltLoop:\r
+    cli\r
+    hlt\r
+    jmp        HltLoop\r
+    ret\r
+AsmRelocateApLoopEnd:\r
+\r
 ;-------------------------------------------------------------------------------------\r
 ;  AsmGetAddressMap (&AddressMap);\r
 ;-------------------------------------------------------------------------------------\r
index 28a3cd4b82686d2e67f1e9fefd3dbfe5e7287975..39ec5def5ba741334d0c75ec13c5b9c82269470c 100644 (file)
@@ -60,5 +60,26 @@ typedef struct {
 } MP_CPU_EXCHANGE_INFO;\r
 \r
 #pragma pack()\r
+/**\r
+  Assembly code to place AP into safe loop mode.\r
+\r
+  Place AP into targeted C-State if MONITOR is supported, otherwise\r
+  place AP into hlt state.\r
+  Place AP in protected mode if the current is long mode. Due to AP maybe\r
+  wakeup by some hardware event. It could avoid accessing page table that\r
+  may not available during booting to OS.\r
+\r
+  @param[in] MwaitSupport    TRUE indicates MONITOR is supported.\r
+                             FALSE indicates MONITOR is not supported.\r
+  @param[in] ApTargetCState  Target C-State value.\r
+  @param[in] PmCodeSegment   Protected mode code segment value.\r
+**/\r
+typedef\r
+VOID\r
+(EFIAPI * ASM_RELOCATE_AP_LOOP) (\r
+  IN BOOLEAN                 MwaitSupport,\r
+  IN UINTN                   ApTargetCState,\r
+  IN UINTN                   PmCodeSegment\r
+  );\r
 #endif\r
 \r
index 3c55ffaafecc53b37ba96417b9ea9e43a0000885..d5d7efe2921cb30d20fec3be8fc6864a026fa940 100644 (file)
@@ -176,6 +176,60 @@ CProcedureInvoke:
 \r
 RendezvousFunnelProcEnd:\r
 \r
+;-------------------------------------------------------------------------------------\r
+;  AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment);\r
+;-------------------------------------------------------------------------------------\r
+global ASM_PFX(AsmRelocateApLoop)\r
+ASM_PFX(AsmRelocateApLoop):\r
+AsmRelocateApLoopStart:\r
+    push       rcx\r
+    push       rdx\r
+\r
+    lea        rsi, [PmEntry]    ; rsi <- The start address of transition code\r
+\r
+    push       r8\r
+    push       rsi\r
+    DB         0x48\r
+    retf\r
+BITS 32\r
+PmEntry:\r
+    mov        eax, cr0\r
+    btr        eax, 31           ; Clear CR0.PG\r
+    mov        cr0, eax          ; Disable paging and caches\r
+\r
+    mov        ebx, edx          ; Save EntryPoint to rbx, for rdmsr will overwrite rdx\r
+    mov        ecx, 0xc0000080\r
+    rdmsr\r
+    and        ah, ~ 1           ; Clear LME\r
+    wrmsr\r
+    mov        eax, cr4\r
+    and        al, ~ (1 << 5)    ; Clear PAE\r
+    mov        cr4, eax\r
+\r
+    pop        edx\r
+    add        esp, 4\r
+    pop        ecx,\r
+    add        esp, 4\r
+    cmp        cl, 1              ; Check mwait-monitor support\r
+    jnz        HltLoop\r
+    mov        ebx, edx           ; Save C-State to ebx\r
+MwaitLoop:\r
+    mov        eax, esp           ; Set Monitor Address\r
+    xor        ecx, ecx           ; ecx = 0\r
+    xor        edx, edx           ; edx = 0\r
+    monitor\r
+    shl        ebx, 4\r
+    mov        eax, ebx           ; Mwait Cx, Target C-State per eax[7:4]\r
+    mwait\r
+    jmp        MwaitLoop\r
+HltLoop:\r
+    cli\r
+    hlt\r
+    jmp        HltLoop\r
+    ret\r
+BITS 64\r
+AsmRelocateApLoopEnd:\r
+\r
 ;-------------------------------------------------------------------------------------\r
 ;  AsmGetAddressMap (&AddressMap);\r
 ;-------------------------------------------------------------------------------------\r