UefiCpuPkg/BaseXApic[X2]ApicLib: Implements AMD extended cpu topology

This patch adds support for AMD's new extended topology.
If processor supports CPUID 80000026 leaf then obtain
the topology information using new method.

Algorithm:
  if CPUID is AMD:
    then
     check for AMD's extended cpu tology leaf.
     if yes
       then extract cpu tology based on
       AMD programmer manual's instruction.
     else
       then fallback to existing topology function.
    endif
  endif

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Abdul Lateef Attar <AbdulLateef.Attar@amd.com>
Message-Id: <d93822d37fd25dafd32795758cf47263b432e102.1705549445.git.AbdulLateef.Attar@amd.com>
Acked-by: Ray Ni <ray.ni@intel.com>
Acked-by: Tom Lendacky <thomas.lendacky@amd.com>
This commit is contained in:
Abdul Lateef Attar 2024-01-18 09:24:09 +05:30 committed by mergify[bot]
parent d14526372d
commit 0e9b124f9c
2 changed files with 250 additions and 2 deletions

View File

@ -4,7 +4,7 @@
This local APIC library instance supports xAPIC mode only.
Copyright (c) 2010 - 2023, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2017 - 2020, AMD Inc. All rights reserved.<BR>
Copyright (c) 2017 - 2024, AMD Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@ -1157,6 +1157,125 @@ GetProcessorLocationByApicId (
}
}
/**
Get Package ID/Die ID/Module ID/Core ID/Thread ID of a AMD processor family.
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 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 zero.
@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
AmdGetProcessorLocation2ByApicId (
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_EBX ExtendedTopologyEbx;
CPUID_EXTENDED_TOPOLOGY_ECX ExtendedTopologyEcx;
UINT32 MaxExtendedCpuIdIndex;
UINT32 TopologyLevel;
UINT32 PreviousLevel;
UINT32 Data;
if (Die != NULL) {
*Die = 0;
}
if (Tile != NULL) {
*Tile = 0;
}
if (Module != NULL) {
*Module = 0;
}
PreviousLevel = 0;
TopologyLevel = 0;
/// Check if extended toplogy supported
AsmCpuid (CPUID_EXTENDED_FUNCTION, &MaxExtendedCpuIdIndex, NULL, NULL, NULL);
if (MaxExtendedCpuIdIndex >= AMD_CPUID_EXTENDED_TOPOLOGY) {
do {
AsmCpuidEx (
AMD_CPUID_EXTENDED_TOPOLOGY,
TopologyLevel,
&ExtendedTopologyEax.Uint32,
&ExtendedTopologyEbx.Uint32,
&ExtendedTopologyEcx.Uint32,
NULL
);
if (ExtendedTopologyEbx.Bits.LogicalProcessors == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID) {
/// if this fails at first level
/// then will fall back to non-extended topology
break;
}
Data = InitialApicId >> PreviousLevel;
Data &= (1 << (ExtendedTopologyEax.Bits.ApicIdShift - PreviousLevel)) - 1;
switch (ExtendedTopologyEcx.Bits.LevelType) {
case CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT:
if (Thread != NULL) {
*Thread = Data;
}
break;
case CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE:
if (Core != NULL) {
*Core = Data;
}
break;
case CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_MODULE:
if (Module != NULL) {
*Module = Data;
}
break;
case CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_TILE:
if (Die != NULL) {
*Die = Data;
}
break;
default:
break;
}
TopologyLevel++;
PreviousLevel = ExtendedTopologyEax.Bits.ApicIdShift;
} while (ExtendedTopologyEbx.Bits.LogicalProcessors != CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID);
if (Package != NULL) {
*Package = InitialApicId >> PreviousLevel;
}
}
/// If extended topology CPUID is not supported
/// OR, execution of AMD_CPUID_EXTENDED_TOPOLOGY at level 0 fails(return 0).
if (TopologyLevel == 0) {
GetProcessorLocationByApicId (InitialApicId, Package, Core, Thread);
}
return;
}
/**
Get Package ID/Die ID/Tile ID/Module ID/Core ID/Thread ID of a processor.
@ -1194,6 +1313,11 @@ GetProcessorLocation2ByApicId (
UINT32 Bits[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_DIE + 2];
UINT32 *Location[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_DIE + 2];
if (StandardSignatureIsAuthenticAMD ()) {
AmdGetProcessorLocation2ByApicId (InitialApicId, Package, Die, Tile, Module, Core, Thread);
return;
}
for (LevelType = 0; LevelType < ARRAY_SIZE (Bits); LevelType++) {
Bits[LevelType] = 0;
}

View File

@ -5,7 +5,7 @@
which have xAPIC and x2APIC modes.
Copyright (c) 2010 - 2023, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2017 - 2020, AMD Inc. All rights reserved.<BR>
Copyright (c) 2017 - 2024, AMD Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@ -1396,6 +1396,125 @@ GetProcessorLocationByApicId (
}
}
/**
Get Package ID/Die ID/Module ID/Core ID/Thread ID of a AMD processor family.
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 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 zero.
@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
AmdGetProcessorLocation2ByApicId (
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_EBX ExtendedTopologyEbx;
CPUID_EXTENDED_TOPOLOGY_ECX ExtendedTopologyEcx;
UINT32 MaxExtendedCpuIdIndex;
UINT32 TopologyLevel;
UINT32 PreviousLevel;
UINT32 Data;
if (Die != NULL) {
*Die = 0;
}
if (Tile != NULL) {
*Tile = 0;
}
if (Module != NULL) {
*Module = 0;
}
PreviousLevel = 0;
TopologyLevel = 0;
/// Check if extended toplogy supported
AsmCpuid (CPUID_EXTENDED_FUNCTION, &MaxExtendedCpuIdIndex, NULL, NULL, NULL);
if (MaxExtendedCpuIdIndex >= AMD_CPUID_EXTENDED_TOPOLOGY) {
do {
AsmCpuidEx (
AMD_CPUID_EXTENDED_TOPOLOGY,
TopologyLevel,
&ExtendedTopologyEax.Uint32,
&ExtendedTopologyEbx.Uint32,
&ExtendedTopologyEcx.Uint32,
NULL
);
if (ExtendedTopologyEbx.Bits.LogicalProcessors == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID) {
/// if this fails at first level
/// then will fall back to non-extended topology
break;
}
Data = InitialApicId >> PreviousLevel;
Data &= (1 << (ExtendedTopologyEax.Bits.ApicIdShift - PreviousLevel)) - 1;
switch (ExtendedTopologyEcx.Bits.LevelType) {
case CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT:
if (Thread != NULL) {
*Thread = Data;
}
break;
case CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE:
if (Core != NULL) {
*Core = Data;
}
break;
case CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_MODULE:
if (Module != NULL) {
*Module = Data;
}
break;
case CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_TILE:
if (Die != NULL) {
*Die = Data;
}
break;
default:
break;
}
TopologyLevel++;
PreviousLevel = ExtendedTopologyEax.Bits.ApicIdShift;
} while (ExtendedTopologyEbx.Bits.LogicalProcessors != CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID);
if (Package != NULL) {
*Package = InitialApicId >> PreviousLevel;
}
}
/// If extended topology CPUID is not supported
/// OR, execution of AMD_CPUID_EXTENDED_TOPOLOGY at level 0 fails(return 0).
if (TopologyLevel == 0) {
GetProcessorLocationByApicId (InitialApicId, Package, Core, Thread);
}
return;
}
/**
Get Package ID/Die ID/Tile ID/Module ID/Core ID/Thread ID of a processor.
@ -1433,6 +1552,11 @@ GetProcessorLocation2ByApicId (
UINT32 Bits[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_DIE + 2];
UINT32 *Location[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_DIE + 2];
if (StandardSignatureIsAuthenticAMD ()) {
AmdGetProcessorLocation2ByApicId (InitialApicId, Package, Die, Tile, Module, Core, Thread);
return;
}
for (LevelType = 0; LevelType < ARRAY_SIZE (Bits); LevelType++) {
Bits[LevelType] = 0;
}