* [PATCH v2] UefiCpuPkg/LocalApicLib: Add GetProcessorLocation2ByApicId() API
@ 2019-04-04 7:48 Ni, Ray
2019-04-04 12:28 ` [edk2-devel] " Dong, Eric
0 siblings, 1 reply; 2+ messages in thread
From: Ni, Ray @ 2019-04-04 7:48 UTC (permalink / raw)
To: devel; +Cc: Eric Dong, Star Zeng, Zhiqiang Qin
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.ni@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Zhiqiang Qin <zhiqiang.qin@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
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [edk2-devel] [PATCH v2] UefiCpuPkg/LocalApicLib: Add GetProcessorLocation2ByApicId() API
2019-04-04 7:48 [PATCH v2] UefiCpuPkg/LocalApicLib: Add GetProcessorLocation2ByApicId() API Ni, Ray
@ 2019-04-04 12:28 ` Dong, Eric
0 siblings, 0 replies; 2+ messages in thread
From: Dong, Eric @ 2019-04-04 12:28 UTC (permalink / raw)
To: devel@edk2.groups.io, Ni, Ray; +Cc: Zeng, Star, Qin, Zhiqiang
Reviewed-by: Eric Dong <eric.dong@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.dong@intel.com>; Zeng, Star <star.zeng@intel.com>; Qin,
> Zhiqiang <zhiqiang.qin@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.ni@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Zhiqiang Qin <zhiqiang.qin@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
>
>
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2019-04-04 12:28 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-04-04 7:48 [PATCH v2] UefiCpuPkg/LocalApicLib: Add GetProcessorLocation2ByApicId() API Ni, Ray
2019-04-04 12:28 ` [edk2-devel] " Dong, Eric
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox