Reviewed-by:  Eric Dong <eric.d...@intel.com>

> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of Ni,
> Ray
> Sent: Thursday, April 4, 2019 3:49 PM
> To: devel@edk2.groups.io
> Cc: Dong, Eric <eric.d...@intel.com>; Zeng, Star <star.z...@intel.com>; Qin,
> Zhiqiang <zhiqiang....@intel.com>
> Subject: [edk2-devel] [PATCH v2] UefiCpuPkg/LocalApicLib: Add
> GetProcessorLocation2ByApicId() API
> 
> 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>
> Cc: Star Zeng <star.z...@intel.com>
> Cc: Zhiqiang Qin <zhiqiang....@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..fd8c494a9f 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_EXTENDED_TOPOLOGY_EAX         ExtendedTopologyEax;
> +  CPUID_EXTENDED_TOPOLOGY_ECX         ExtendedTopologyEcx;
> +  UINT32                              MaxStandardCpuIdIndex;
> +  UINT32                              Index;
> +  UINTN                               LevelType;
> +  UINT32
> Bits[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_DIE + 2];
> +  UINT32
> *Location[CPUID_V2_EXTENDED_TOPOLOGY_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) {
> +    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,
> +      Index,
> +      &ExtendedTopologyEax.Uint32,
> +      NULL,
> +      &ExtendedTopologyEcx.Uint32,
> +      NULL
> +      );
> +
> +    LevelType = ExtendedTopologyEcx.Bits.LevelType;
> +
> +    //
> +    // first level reported should be SMT.
> +    //
> +    ASSERT ((Index != 0) || (LevelType ==
> CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT));
> +    if (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID) {
> +      break;
> +    }
> +    ASSERT (LevelType < ARRAY_SIZE (Bits));
> +    Bits[LevelType] = ExtendedTopologyEax.Bits.ApicIdShift;
> +  }
> +
> +  for (LevelType = CPUID_EXTENDED_TOPOLOGY_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_LEVEL_TYPE_DIE + 1] = Package;
> +  Location[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_DIE    ] = Die;
> +  Location[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_TILE   ] = Tile;
> +  Location[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_MODULE ] =
> Module;
> +  Location[CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE   ]    = Core;
> +  Location[CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT    ]    = Thread;
> +
> +  Bits[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_DIE + 1] = 32;
> +
> +  for ( LevelType = CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT
> +      ; LevelType <= CPUID_V2_EXTENDED_TOPOLOGY_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..79338186fb 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_EXTENDED_TOPOLOGY_EAX         ExtendedTopologyEax;
> +  CPUID_EXTENDED_TOPOLOGY_ECX         ExtendedTopologyEcx;
> +  UINT32                              MaxStandardCpuIdIndex;
> +  UINT32                              Index;
> +  UINTN                               LevelType;
> +  UINT32
> Bits[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_DIE + 2];
> +  UINT32
> *Location[CPUID_V2_EXTENDED_TOPOLOGY_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) {
> +    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,
> +      Index,
> +      &ExtendedTopologyEax.Uint32,
> +      NULL,
> +      &ExtendedTopologyEcx.Uint32,
> +      NULL
> +      );
> +
> +    LevelType = ExtendedTopologyEcx.Bits.LevelType;
> +
> +    //
> +    // first level reported should be SMT.
> +    //
> +    ASSERT ((Index != 0) || (LevelType ==
> CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT));
> +    if (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID) {
> +      break;
> +    }
> +    ASSERT (LevelType < ARRAY_SIZE (Bits));
> +    Bits[LevelType] = ExtendedTopologyEax.Bits.ApicIdShift;
> +  }
> +
> +  for (LevelType = CPUID_EXTENDED_TOPOLOGY_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_LEVEL_TYPE_DIE + 1] = Package;
> +  Location[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_DIE    ] = Die;
> +  Location[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_TILE   ] = Tile;
> +  Location[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_MODULE ] =
> Module;
> +  Location[CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE   ]    = Core;
> +  Location[CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT    ]    = Thread;
> +
> +  Bits[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_DIE + 1] = 32;
> +
> +  for ( LevelType = CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT
> +      ; LevelType <= CPUID_V2_EXTENDED_TOPOLOGY_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
> 
> 
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#49): https://edk2.groups.io/g/devel/message/49
Mute This Topic: https://groups.io/mt/30894207/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to