GetProcessorLocation2ByApicId() extracts the
package/die/tile/module/core/thread ID from the initial APIC ID.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ray Ni <ray...@intel.com>
Cc: Eric Dong <eric.d...@intel.com>
---
 UefiCpuPkg/Include/Library/LocalApicLib.h     |  29 +++-
 .../Library/BaseXApicLib/BaseXApicLib.c       | 125 +++++++++++++++++-
 .../BaseXApicX2ApicLib/BaseXApicX2ApicLib.c   | 125 +++++++++++++++++-
 3 files changed, 276 insertions(+), 3 deletions(-)

diff --git a/UefiCpuPkg/Include/Library/LocalApicLib.h 
b/UefiCpuPkg/Include/Library/LocalApicLib.h
index ad1c26df60..ffe60c56fc 100644
--- a/UefiCpuPkg/Include/Library/LocalApicLib.h
+++ b/UefiCpuPkg/Include/Library/LocalApicLib.h
@@ -4,7 +4,7 @@
   Local APIC library assumes local APIC is enabled. It does not
   handles cases where local APIC is disabled.
 
-  Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
   This program and the accompanying materials
   are licensed and made available under the terms and conditions of the BSD 
License
   which accompanies this distribution.  The full text of the license may be 
found at
@@ -432,5 +432,32 @@ GetProcessorLocationByApicId (
   OUT UINT32  *Thread  OPTIONAL
   );
 
+/**
+  Get Package ID/Module ID/Tile ID/Die 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 threads per core, number of
+  cores per module, number of modules per tile, number of tiles per die, number
+  of dies per package.
+
+  @param[in]   InitialApicId Initial APIC ID of the target logical processor.
+  @param[out]  Package       Returns the processor package ID.
+  @param[out]  Die           Returns the processor die ID.
+  @param[out]  Tile          Returns the processor tile ID.
+  @param[out]  Module        Returns the processor module ID.
+  @param[out]  Core          Returns the processor core ID.
+  @param[out]  Thread        Returns the processor thread ID.
+**/
+VOID
+EFIAPI
+GetProcessorLocation2ByApicId (
+  IN  UINT32  InitialApicId,
+  OUT UINT32  *Package  OPTIONAL,
+  OUT UINT32  *Die      OPTIONAL,
+  OUT UINT32  *Tile     OPTIONAL,
+  OUT UINT32  *Module   OPTIONAL,
+  OUT UINT32  *Core     OPTIONAL,
+  OUT UINT32  *Thread   OPTIONAL
+  );
 #endif
 
diff --git a/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c 
b/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
index 7d66d89dfd..1f994c81cf 100644
--- a/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
+++ b/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
@@ -3,7 +3,7 @@
 
   This local APIC library instance supports xAPIC mode only.
 
-  Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
   Copyright (c) 2017, AMD Inc. All rights reserved.<BR>
 
   This program and the accompanying materials
@@ -1156,3 +1156,126 @@ GetProcessorLocationByApicId (
     *Package = (InitialApicId >> (ThreadBits + CoreBits));
   }
 }
+
+/**
+  Get Package ID/Die ID/Tile ID/Module 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 threads per core, number of
+  cores per module, number of modules per tile, number of tiles per die, number
+  of dies per package.
+
+  @param[in]   InitialApicId Initial APIC ID of the target logical processor.
+  @param[out]  Package       Returns the processor package ID.
+  @param[out]  Die           Returns the processor die ID.
+  @param[out]  Tile          Returns the processor tile ID.
+  @param[out]  Module        Returns the processor module ID.
+  @param[out]  Core          Returns the processor core ID.
+  @param[out]  Thread        Returns the processor thread ID.
+**/
+VOID
+EFIAPI
+GetProcessorLocation2ByApicId (
+  IN  UINT32  InitialApicId,
+  OUT UINT32  *Package  OPTIONAL,
+  OUT UINT32  *Die      OPTIONAL,
+  OUT UINT32  *Tile     OPTIONAL,
+  OUT UINT32  *Module   OPTIONAL,
+  OUT UINT32  *Core     OPTIONAL,
+  OUT UINT32  *Thread   OPTIONAL
+  )
+{
+  CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_EAX V2ExtendedTopologyEax;
+  CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_ECX V2ExtendedTopologyEcx;
+  UINT32                                     MaxStandardCpuIdIndex;
+  UINT32                                     Index;
+  UINTN                                      LevelType;
+  UINT32                                     
Bits[CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_DIE + 2];
+  UINT32                                     
*Location[CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_DIE + 2];
+
+  for (LevelType = 0; LevelType < ARRAY_SIZE (Bits); LevelType++) {
+    Bits[LevelType] = 0;
+  }
+
+  //
+  // Get max index of CPUID
+  //
+  AsmCpuid (CPUID_SIGNATURE, &MaxStandardCpuIdIndex, NULL, NULL, NULL);
+  if (MaxStandardCpuIdIndex < CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION) {
+    if (Die != NULL) {
+      *Die = 0;
+    }
+    if (Tile != NULL) {
+      *Tile = 0;
+    }
+    if (Module != NULL) {
+      *Module = 0;
+    }
+    GetProcessorLocationByApicId (InitialApicId, Package, Core, Thread);
+    return;
+  }
+
+  //
+  // If the V2 extended topology enumeration leaf is available, it
+  // is the preferred mechanism for enumerating topology.
+  //
+  for (Index = 0; ; Index++) {
+    AsmCpuidEx(
+      CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION,
+      Index,
+      &V2ExtendedTopologyEax.Uint32,
+      NULL,
+      &V2ExtendedTopologyEcx.Uint32,
+      NULL
+      );
+
+    LevelType = V2ExtendedTopologyEcx.Bits.LevelType;
+
+    //
+    // first level reported should be SMT.
+    //
+    ASSERT ((Index != 0) || (LevelType == 
CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_SMT));
+    if (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID) {
+      break;
+    }
+    ASSERT (LevelType < ARRAY_SIZE (Bits));
+    Bits[LevelType] = V2ExtendedTopologyEax.Bits.BitsNum;
+  }
+
+  for (LevelType = CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_CORE; 
LevelType < ARRAY_SIZE (Bits); LevelType++) {
+    //
+    // If there are more levels between level-1 (low-level) and level-2 
(high-level), the unknown levels will be ignored
+    // and treated as an extension of the last known level (i.e., level-1 in 
this case).
+    //
+    if (Bits[LevelType] == 0) {
+      Bits[LevelType] = Bits[LevelType - 1];
+    }
+  }
+
+  Location[CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_DIE + 1] = 
Package;
+  Location[CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_DIE    ] = Die;
+  Location[CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_TILE   ] = Tile;
+  Location[CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_MODULE ] = Module;
+  Location[CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_CORE   ] = Core;
+  Location[CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_SMT    ] = Thread;
+
+  Bits[CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_DIE + 1] = 32;
+
+  for ( LevelType = CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_SMT
+      ; LevelType <= CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_DIE + 1
+      ; LevelType ++
+      ) {
+    if (Location[LevelType] != NULL) {
+      //
+      // Bits[i] holds the number of bits to shift right on x2APIC ID to get a 
unique
+      // topology ID of the next level type.
+      //
+      *Location[LevelType] = InitialApicId >> Bits[LevelType - 1];
+
+      //
+      // Bits[i] - Bits[i-1] holds the number of bits for the next ONE level 
type.
+      //
+      *Location[LevelType] &= (1 << (Bits[LevelType] - Bits[LevelType - 1])) - 
1;
+    }
+  }
+}
diff --git a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c 
b/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c
index 6b89faf3df..7450b194b6 100644
--- a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c
+++ b/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c
@@ -4,7 +4,7 @@
   This local APIC library instance supports x2APIC capable processors
   which have xAPIC and x2APIC modes.
 
-  Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
   Copyright (c) 2017, AMD Inc. All rights reserved.<BR>
 
   This program and the accompanying materials
@@ -1251,3 +1251,126 @@ GetProcessorLocationByApicId (
     *Package = (InitialApicId >> (ThreadBits + CoreBits));
   }
 }
+
+/**
+  Get Package ID/Die ID/Tile ID/Module 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 threads per core, number of
+  cores per module, number of modules per tile, number of tiles per die, number
+  of dies per package.
+
+  @param[in]   InitialApicId Initial APIC ID of the target logical processor.
+  @param[out]  Package       Returns the processor package ID.
+  @param[out]  Die           Returns the processor die ID.
+  @param[out]  Tile          Returns the processor tile ID.
+  @param[out]  Module        Returns the processor module ID.
+  @param[out]  Core          Returns the processor core ID.
+  @param[out]  Thread        Returns the processor thread ID.
+**/
+VOID
+EFIAPI
+GetProcessorLocation2ByApicId (
+  IN  UINT32  InitialApicId,
+  OUT UINT32  *Package  OPTIONAL,
+  OUT UINT32  *Die      OPTIONAL,
+  OUT UINT32  *Tile     OPTIONAL,
+  OUT UINT32  *Module   OPTIONAL,
+  OUT UINT32  *Core     OPTIONAL,
+  OUT UINT32  *Thread   OPTIONAL
+  )
+{
+  CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_EAX V2ExtendedTopologyEax;
+  CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_ECX V2ExtendedTopologyEcx;
+  UINT32                                     MaxStandardCpuIdIndex;
+  UINT32                                     Index;
+  UINTN                                      LevelType;
+  UINT32                                     
Bits[CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_DIE + 2];
+  UINT32                                     
*Location[CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_DIE + 2];
+
+  for (LevelType = 0; LevelType < ARRAY_SIZE (Bits); LevelType++) {
+    Bits[LevelType] = 0;
+  }
+
+  //
+  // Get max index of CPUID
+  //
+  AsmCpuid (CPUID_SIGNATURE, &MaxStandardCpuIdIndex, NULL, NULL, NULL);
+  if (MaxStandardCpuIdIndex < CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION) {
+    if (Die != NULL) {
+      *Die = 0;
+    }
+    if (Tile != NULL) {
+      *Tile = 0;
+    }
+    if (Module != NULL) {
+      *Module = 0;
+    }
+    GetProcessorLocationByApicId (InitialApicId, Package, Core, Thread);
+    return;
+  }
+
+  //
+  // If the V2 extended topology enumeration leaf is available, it
+  // is the preferred mechanism for enumerating topology.
+  //
+  for (Index = 0; ; Index++) {
+    AsmCpuidEx(
+      CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION,
+      Index,
+      &V2ExtendedTopologyEax.Uint32,
+      NULL,
+      &V2ExtendedTopologyEcx.Uint32,
+      NULL
+      );
+
+    LevelType = V2ExtendedTopologyEcx.Bits.LevelType;
+
+    //
+    // first level reported should be SMT.
+    //
+    ASSERT ((Index != 0) || (LevelType == 
CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_SMT));
+    if (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID) {
+      break;
+    }
+    ASSERT (LevelType < ARRAY_SIZE (Bits));
+    Bits[LevelType] = V2ExtendedTopologyEax.Bits.BitsNum;
+  }
+
+  for (LevelType = CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_CORE; 
LevelType < ARRAY_SIZE (Bits); LevelType++) {
+    //
+    // If there are more levels between level-1 (low-level) and level-2 
(high-level), the unknown levels will be ignored
+    // and treated as an extension of the last known level (i.e., level-1 in 
this case).
+    //
+    if (Bits[LevelType] == 0) {
+      Bits[LevelType] = Bits[LevelType - 1];
+    }
+  }
+
+  Location[CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_DIE + 1] = 
Package;
+  Location[CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_DIE    ] = Die;
+  Location[CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_TILE   ] = Tile;
+  Location[CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_MODULE ] = Module;
+  Location[CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_CORE   ] = Core;
+  Location[CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_SMT    ] = Thread;
+
+  Bits[CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_DIE + 1] = 32;
+
+  for ( LevelType = CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_SMT
+      ; LevelType <= CPUID_V2_EXTENDED_TOPOLOGY_ENUMERATION_LEVEL_TYPE_DIE + 1
+      ; LevelType ++
+      ) {
+    if (Location[LevelType] != NULL) {
+      //
+      // Bits[i] holds the number of bits to shift right on x2APIC ID to get a 
unique
+      // topology ID of the next level type.
+      //
+      *Location[LevelType] = InitialApicId >> Bits[LevelType - 1];
+
+      //
+      // Bits[i] - Bits[i-1] holds the number of bits for the next ONE level 
type.
+      //
+      *Location[LevelType] &= (1 << (Bits[LevelType] - Bits[LevelType - 1])) - 
1;
+    }
+  }
+}
-- 
2.21.0.windows.1

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

Reply via email to