summaryrefslogtreecommitdiffstats
path: root/UefiCpuPkg/Library/BaseXApicLib
diff options
context:
space:
mode:
authorLeo Duran <leo.duran@amd.com>2016-11-01 03:42:57 +0800
committerJeff Fan <jeff.fan@intel.com>2016-11-01 09:08:45 +0800
commit73152f19c0be7f31ee05f32878b515a296c487fa (patch)
tree4d621f3537167e6cdac8bb275f3e9cbcf5460afe /UefiCpuPkg/Library/BaseXApicLib
parentac55b925548f3b33f2bc93e603ecffe4a6cb191a (diff)
downloadedk2-73152f19c0be7f31ee05f32878b515a296c487fa.tar.gz
edk2-73152f19c0be7f31ee05f32878b515a296c487fa.tar.bz2
edk2-73152f19c0be7f31ee05f32878b515a296c487fa.zip
UefiCpuPkg: Move GetProcessorLocation() to LocalApicLib library
1) Remove SmmGetProcessorLocation() from PiSmmCpuDxeSmm driver. 2) Remove ExtractProcessorLocation() from MpInitLib library. 3) Add GetProcessorLocation() to BaseXApicLib and BaseXApicX2ApicLib. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Leo Duran <leo.duran@amd.com> Signed-off-by: Michael Kinney <Michael.d.kinney@intel.com> Tested-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Michael Kinney <Michael.d.kinney@intel.com> Reviewed-by: Jeff Fan <jeff.fan@intel.com>
Diffstat (limited to 'UefiCpuPkg/Library/BaseXApicLib')
-rw-r--r--UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c b/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
index 8d0fb02109..5976403456 100644
--- a/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
+++ b/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
@@ -941,3 +941,149 @@ GetApicMsiValue (
}
return MsiData.Uint64;
}
+
+/**
+ Get Package ID/Core ID/Thread ID of a processor.
+
+ The algorithm assumes the target system has symmetry across physical
+ package boundaries with respect to the number of logical processors
+ per package, number of cores per package.
+
+ @param[in] InitialApicId Initial APIC ID of the target logical processor.
+ @param[out] Package Returns the processor package ID.
+ @param[out] Core Returns the processor core ID.
+ @param[out] Thread Returns the processor thread ID.
+**/
+VOID
+GetProcessorLocation(
+ IN UINT32 InitialApicId,
+ OUT UINT32 *Package OPTIONAL,
+ OUT UINT32 *Core OPTIONAL,
+ OUT UINT32 *Thread OPTIONAL
+ )
+{
+ BOOLEAN TopologyLeafSupported;
+ UINTN ThreadBits;
+ UINTN CoreBits;
+ CPUID_VERSION_INFO_EBX VersionInfoEbx;
+ CPUID_VERSION_INFO_EDX VersionInfoEdx;
+ CPUID_CACHE_PARAMS_EAX CacheParamsEax;
+ CPUID_EXTENDED_TOPOLOGY_EAX ExtendedTopologyEax;
+ CPUID_EXTENDED_TOPOLOGY_EBX ExtendedTopologyEbx;
+ CPUID_EXTENDED_TOPOLOGY_ECX ExtendedTopologyEcx;
+ UINT32 MaxCpuIdIndex;
+ UINT32 SubIndex;
+ UINTN LevelType;
+ UINT32 MaxLogicProcessorsPerPackage;
+ UINT32 MaxCoresPerPackage;
+
+ //
+ // Check if the processor is capable of supporting more than one logical processor.
+ //
+ AsmCpuid(CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);
+ if (VersionInfoEdx.Bits.HTT == 0) {
+ if (Thread != NULL) {
+ *Thread = 0;
+ }
+ if (Core != NULL) {
+ *Core = 0;
+ }
+ if (Package != NULL) {
+ *Package = 0;
+ }
+ return;
+ }
+
+ ThreadBits = 0;
+ CoreBits = 0;
+
+ //
+ // Assume three-level mapping of APIC ID: Package:Core:SMT.
+ //
+ TopologyLeafSupported = FALSE;
+
+ //
+ // Get the max index of basic CPUID
+ //
+ AsmCpuid(CPUID_SIGNATURE, &MaxCpuIdIndex, NULL, NULL, NULL);
+
+ //
+ // If the extended topology enumeration leaf is available, it
+ // is the preferred mechanism for enumerating topology.
+ //
+ if (MaxCpuIdIndex >= CPUID_EXTENDED_TOPOLOGY) {
+ AsmCpuidEx(
+ CPUID_EXTENDED_TOPOLOGY,
+ 0,
+ &ExtendedTopologyEax.Uint32,
+ &ExtendedTopologyEbx.Uint32,
+ &ExtendedTopologyEcx.Uint32,
+ NULL
+ );
+ //
+ // If CPUID.(EAX=0BH, ECX=0H):EBX returns zero and maximum input value for
+ // basic CPUID information is greater than 0BH, then CPUID.0BH leaf is not
+ // supported on that processor.
+ //
+ if (ExtendedTopologyEbx.Uint32 != 0) {
+ TopologyLeafSupported = TRUE;
+
+ //
+ // Sub-leaf index 0 (ECX= 0 as input) provides enumeration parameters to extract
+ // the SMT sub-field of x2APIC ID.
+ //
+ LevelType = ExtendedTopologyEcx.Bits.LevelType;
+ ASSERT(LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT);
+ ThreadBits = ExtendedTopologyEax.Bits.ApicIdShift;
+
+ //
+ // Software must not assume any "level type" encoding
+ // value to be related to any sub-leaf index, except sub-leaf 0.
+ //
+ SubIndex = 1;
+ do {
+ AsmCpuidEx(
+ CPUID_EXTENDED_TOPOLOGY,
+ SubIndex,
+ &ExtendedTopologyEax.Uint32,
+ NULL,
+ &ExtendedTopologyEcx.Uint32,
+ NULL
+ );
+ LevelType = ExtendedTopologyEcx.Bits.LevelType;
+ if (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE) {
+ CoreBits = ExtendedTopologyEax.Bits.ApicIdShift - ThreadBits;
+ break;
+ }
+ SubIndex++;
+ } while (LevelType != CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID);
+ }
+ }
+
+ if (!TopologyLeafSupported) {
+ AsmCpuid(CPUID_VERSION_INFO, NULL, &VersionInfoEbx.Uint32, NULL, NULL);
+ MaxLogicProcessorsPerPackage = VersionInfoEbx.Bits.MaximumAddressableIdsForLogicalProcessors;
+ if (MaxCpuIdIndex >= CPUID_CACHE_PARAMS) {
+ AsmCpuidEx(CPUID_CACHE_PARAMS, 0, &CacheParamsEax.Uint32, NULL, NULL, NULL);
+ MaxCoresPerPackage = CacheParamsEax.Bits.MaximumAddressableIdsForLogicalProcessors + 1;
+ }
+ else {
+ //
+ // Must be a single-core processor.
+ //
+ MaxCoresPerPackage = 1;
+ }
+
+ ThreadBits = (UINTN)(HighBitSet32(MaxLogicProcessorsPerPackage / MaxCoresPerPackage - 1) + 1);
+ CoreBits = (UINTN)(HighBitSet32(MaxCoresPerPackage - 1) + 1); }
+
+ if (Thread != NULL) {
+ *Thread = InitialApicId & ((1 << ThreadBits) - 1);
+ }
+ if (Core != NULL) {
+ *Core = (InitialApicId >> ThreadBits) & ((1 << CoreBits) - 1);
+ }
+ if (Package != NULL) {
+ *Package = (InitialApicId >> (ThreadBits + CoreBits));
+ }
+}