From 9ebcf0f4005239abcde5141414703e2676200550 Mon Sep 17 00:00:00 2001 From: Jeff Fan Date: Wed, 20 Jul 2016 23:32:17 +0800 Subject: [PATCH] UefiCpuPkg/MpInitLib: Get ApLoopMode and MointorFilter size Firstly, get ApLoopMode from PcdCpuApLoopMode. If MonitorMwait feature is not supported, update ApLoopMode to ApHltLoop. If MonitorMwait feature is supported, get MointorFilter size by CPUID.[EAX=05H]:EBX.BIT0-15. v5: 1. Add comment block for enum AP_LOOP_MODE. Cc: Michael Kinney Cc: Feng Tian Cc: Giri P Mudusuru Cc: Laszlo Ersek Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jeff Fan Reviewed-by: Michael Kinney Tested-by: Laszlo Ersek Tested-by: Michael Kinney --- UefiCpuPkg/Library/MpInitLib/MpLib.c | 63 ++++++++++++++++++++++++++++ UefiCpuPkg/Library/MpInitLib/MpLib.h | 10 +++++ 2 files changed, 73 insertions(+) diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c index 3ac79b6a90..32bbaee5cc 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -15,6 +15,65 @@ #include "MpLib.h" +/** + Detect whether Mwait-monitor feature is supported. + + @retval TRUE Mwait-monitor feature is supported. + @retval FALSE Mwait-monitor feature is not supported. +**/ +BOOLEAN +IsMwaitSupport ( + VOID + ) +{ + CPUID_VERSION_INFO_ECX VersionInfoEcx; + + AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &VersionInfoEcx.Uint32, NULL); + return (VersionInfoEcx.Bits.MONITOR == 1) ? TRUE : FALSE; +} + +/** + Get AP loop mode. + + @param[out] MonitorFilterSize Returns the largest monitor-line size in bytes. + + @return The AP loop mode. +**/ +UINT8 +GetApLoopMode ( + OUT UINT32 *MonitorFilterSize + ) +{ + UINT8 ApLoopMode; + CPUID_MONITOR_MWAIT_EBX MonitorMwaitEbx; + + ASSERT (MonitorFilterSize != NULL); + + ApLoopMode = PcdGet8 (PcdCpuApLoopMode); + ASSERT (ApLoopMode >= ApInHltLoop && ApLoopMode <= ApInRunLoop); + if (ApLoopMode == ApInMwaitLoop) { + if (!IsMwaitSupport ()) { + // + // If processor does not support MONITOR/MWAIT feature, + // force AP in Hlt-loop mode + // + ApLoopMode = ApInHltLoop; + } + } + + if (ApLoopMode != ApInMwaitLoop) { + *MonitorFilterSize = sizeof (UINT32); + } else { + // + // CPUID.[EAX=05H]:EBX.BIT0-15: Largest monitor-line size in bytes + // CPUID.[EAX=05H].EDX: C-states supported using MWAIT + // + AsmCpuid (CPUID_MONITOR_MWAIT, NULL, &MonitorMwaitEbx.Uint32, NULL, NULL); + *MonitorFilterSize = MonitorMwaitEbx.Bits.LargestMonitorLineSize; + } + + return ApLoopMode; +} /** MP Initialize Library initialization. @@ -35,10 +94,14 @@ MpInitLibInitialize ( ) { MP_ASSEMBLY_ADDRESS_MAP AddressMap; + UINT32 MonitorFilterSize; + UINT8 ApLoopMode; UINTN ApResetVectorSize; AsmGetAddressMap (&AddressMap); ApResetVectorSize = AddressMap.RendezvousFunnelSize + sizeof (MP_CPU_EXCHANGE_INFO); + ApLoopMode = GetApLoopMode (&MonitorFilterSize); + return EFI_SUCCESS; } diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h index 2be13516aa..317facc80c 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -35,6 +35,16 @@ #include #include +// +// AP loop state when APs are in idle state +// It's value is the same with PcdCpuApLoopMode +// +typedef enum { + ApInHltLoop = 1, + ApInMwaitLoop = 2, + ApInRunLoop = 3 +} AP_LOOP_MODE; + // // AP reset code information including code address and size, // this structure will be shared be C code and assembly code.