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
} 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
\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