mirror of
https://github.com/tianocore/edk2
synced 2026-08-27 00:23:19 -04:00
DynamicTablesPkg: Add ACPI MSCT table generator
Add MSCT table ID to the ESTD_ACPI_TABLE_ID enumeration. Introduces an ACPI MSCT (Maximum System Characteristics Table) generator library that retrieves the following information from the configuration manager: - Maximum physical address - Processor proximity information - Memory proximity information - Clock proximity information The generator calculates: - Maximum memory length per memory domain - Maximum contiguous processor domain - Maximum memory and processor domain combination Signed-off-by: Abdul Lateef Attar <AbdulLateef.Attar@amd.com>
This commit is contained in:
parent
bf395b2c25
commit
76d8918076
9 changed files with 1763 additions and 2 deletions
|
|
@ -2,7 +2,7 @@
|
|||
# Dsc include file for Dynamic Tables Framework.
|
||||
#
|
||||
# Copyright (c) 2017 - 2026, Arm Limited. All rights reserved.<BR>
|
||||
# Copyright (C) 2024 - 2025 Advanced Micro Devices, Inc. All rights reserved.<BR>
|
||||
# Copyright (C) 2024 - 2026 Advanced Micro Devices, Inc. All rights reserved.<BR>
|
||||
# Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
|
@ -41,6 +41,7 @@
|
|||
DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/AcpiFadtLib.inf
|
||||
DynamicTablesPkg/Library/Acpi/Common/AcpiHmatLib/AcpiHmatLib.inf
|
||||
DynamicTablesPkg/Library/Acpi/Common/AcpiMcfgLib/AcpiMcfgLib.inf
|
||||
DynamicTablesPkg/Library/Acpi/Common/AcpiMsctLib/AcpiMsctLib.inf
|
||||
DynamicTablesPkg/Library/Acpi/Common/AcpiPcctLib/AcpiPcctLib.inf
|
||||
DynamicTablesPkg/Library/Acpi/Common/AcpiPpttLib/AcpiPpttLib.inf
|
||||
DynamicTablesPkg/Library/Acpi/Common/AcpiRawLib/AcpiRawLib.inf
|
||||
|
|
@ -105,6 +106,7 @@
|
|||
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/AcpiCedtLib.inf
|
||||
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/AcpiFadtLib.inf
|
||||
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiMcfgLib/AcpiMcfgLib.inf
|
||||
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiMsctLib/AcpiMsctLib.inf
|
||||
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSlitLib/AcpiSlitLib.inf
|
||||
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSpcrLib/AcpiSpcrLib.inf
|
||||
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSpmiLib/AcpiSpmiLib.inf
|
||||
|
|
@ -148,6 +150,7 @@
|
|||
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/AcpiFadtLib.inf
|
||||
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiHmatLib/AcpiHmatLib.inf
|
||||
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiMcfgLib/AcpiMcfgLib.inf
|
||||
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiMsctLib/AcpiMsctLib.inf
|
||||
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiPcctLib/AcpiPcctLib.inf
|
||||
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiPpttLib/AcpiPpttLib.inf
|
||||
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiRawLib/AcpiRawLib.inf
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#
|
||||
# Copyright (c) 2019, Linaro Limited. All rights reserved.<BR>
|
||||
# Copyright (c) 2019 - 2022, Arm Limited. All rights reserved.<BR>
|
||||
# Copyright (C) 2024 - 2025 Advanced Micro Devices, Inc. All rights reserved.<BR>
|
||||
# Copyright (C) 2024 - 2026 Advanced Micro Devices, Inc. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
|
|
@ -32,6 +32,7 @@
|
|||
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
|
||||
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
|
||||
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
|
||||
SortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
|
||||
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
|
||||
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
|
||||
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
|
||||
|
|
|
|||
|
|
@ -91,6 +91,9 @@ The Dynamic Tables Framework implements the following ACPI table generators:
|
|||
Configuration Manager and builds the HEST table.
|
||||
- EINJ : The EINJ generator collates the required platform information from
|
||||
the Configuration Manager and builds the EINJ table.
|
||||
- MSCT : The MSCT (Maximum System Characteristics Table) generator collates
|
||||
the Maximum System Characteristics information from the
|
||||
Configuration Manager and builds the MSCT table.
|
||||
*/
|
||||
|
||||
/** The ACPI_TABLE_GENERATOR_ID type describes ACPI table generator ID.
|
||||
|
|
@ -133,6 +136,7 @@ typedef enum StdAcpiTableId {
|
|||
EStdAcpiTableIdHest, ///< Hest Generator
|
||||
EStdAcpiTableIdEinj, ///< EINJ Generator
|
||||
EStdAcpiTableIdHmat, ///< HMAT Generator
|
||||
EStdAcpiTableIdMsct, ///< MSCT Generator
|
||||
EStdAcpiTableIdMax
|
||||
} ESTD_ACPI_TABLE_ID;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
## @file
|
||||
# ACPI Maximum System Characteristics Table (MSCT) Generator
|
||||
#
|
||||
# Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 1.30
|
||||
BASE_NAME = AcpiMsctLib
|
||||
FILE_GUID = D4F5A6B7-C8D9-4E0A-B1C2-3D4E5F607182
|
||||
VERSION_STRING = 1.0
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
LIBRARY_CLASS = NULL|DXE_DRIVER
|
||||
CONSTRUCTOR = AcpiMsctLibConstructor
|
||||
DESTRUCTOR = AcpiMsctLibDestructor
|
||||
|
||||
[Sources]
|
||||
MsctGenerator.c
|
||||
MsctGenerator.h
|
||||
|
||||
[Sources.x64]
|
||||
X64/X64MsctGenerator.c
|
||||
|
||||
[Sources.AARCH64]
|
||||
Arm/ArmMsctGenerator.c
|
||||
|
||||
[Sources.RISCV64]
|
||||
Default/DefaultMsctGenerator.c
|
||||
|
||||
[Sources.LOONGARCH64]
|
||||
Default/DefaultMsctGenerator.c
|
||||
|
||||
[Packages]
|
||||
DynamicTablesPkg/DynamicTablesPkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
CmObjHelperLib
|
||||
SortLib
|
||||
|
||||
|
|
@ -0,0 +1,249 @@
|
|||
/** @file
|
||||
ARM specific ACPI Maximum System Characteristics Table (MSCT) Generator
|
||||
|
||||
Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
|
||||
// Module specific include files.
|
||||
#include <AcpiTableGenerator.h>
|
||||
#include <ConfigurationManagerObject.h>
|
||||
#include <ConfigurationManagerHelper.h>
|
||||
#include <Library/TableHelperLib.h>
|
||||
#include <Protocol/ConfigurationManagerProtocol.h>
|
||||
#include <Library/CmObjHelperLib.h>
|
||||
|
||||
#include "MsctGenerator.h"
|
||||
|
||||
/**
|
||||
ARM standard MSCT Generator
|
||||
|
||||
Requirements:
|
||||
The following Configuration Manager Object(s) are used by this Generator:
|
||||
- EArmObjGicCInfo (OPTIONAL)
|
||||
*/
|
||||
|
||||
/** This macro expands to a function that retrieves the GIC
|
||||
CPU interface Information from the Configuration Manager.
|
||||
*/
|
||||
GET_OBJECT_LIST (
|
||||
EObjNameSpaceArm,
|
||||
EArmObjGicCInfo,
|
||||
CM_ARM_GICC_INFO
|
||||
);
|
||||
|
||||
/** Get architecture processor domain information.
|
||||
|
||||
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
|
||||
Protocol.
|
||||
@param [out] ProcDomainInfo Pointer to the processor domain information.
|
||||
@param [out] ProcDomainInfoCount Pointer to the count of processor domain
|
||||
information structures.
|
||||
|
||||
@retval EFI_SUCCESS Operation completed successfully.
|
||||
@retval EFI_INVALID_PARAMETER A parameter is invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
|
||||
@retval Other Other EFI_STATUS error from called functions.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetArchProcessorDomainInfo (
|
||||
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
|
||||
OUT UINT32 **ProcDomainInfo,
|
||||
OUT UINT32 *ProcDomainInfoCount
|
||||
)
|
||||
{
|
||||
CM_ARM_GICC_INFO *CmProcDomain;
|
||||
EFI_STATUS Status;
|
||||
UINT32 Index;
|
||||
UINT32 ProcDomainCount;
|
||||
UINT32 *ProcDomain;
|
||||
|
||||
if ((CfgMgrProtocol == NULL) ||
|
||||
(ProcDomainInfo == NULL) ||
|
||||
(ProcDomainInfoCount == NULL))
|
||||
{
|
||||
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CmProcDomain = NULL;
|
||||
ProcDomain = NULL;
|
||||
ProcDomainCount = 0;
|
||||
|
||||
Status = GetEArmObjGicCInfo (
|
||||
CfgMgrProtocol,
|
||||
CM_NULL_TOKEN,
|
||||
&CmProcDomain,
|
||||
&ProcDomainCount
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"ERROR: MSCT: Failed to get GICC Info. Status = %r\n",
|
||||
Status
|
||||
));
|
||||
return Status;
|
||||
}
|
||||
|
||||
ProcDomain = AllocateZeroPool (
|
||||
sizeof (UINT32) *
|
||||
ProcDomainCount
|
||||
);
|
||||
if (ProcDomain == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < ProcDomainCount; Index++) {
|
||||
Status = GetProximityDomainId (
|
||||
CfgMgrProtocol,
|
||||
CmProcDomain[Index].ProximityDomain,
|
||||
CmProcDomain[Index].ProximityDomainToken,
|
||||
&ProcDomain[Index]
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"MSCT: Failed to get Proximity Domain ID for index %d. Status = %r\n",
|
||||
Index,
|
||||
Status
|
||||
));
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
goto error_handler;
|
||||
}
|
||||
}
|
||||
|
||||
*ProcDomainInfo = ProcDomain;
|
||||
*ProcDomainInfoCount = ProcDomainCount;
|
||||
return EFI_SUCCESS;
|
||||
|
||||
error_handler:
|
||||
|
||||
if (ProcDomain != NULL) {
|
||||
FreePool (ProcDomain);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/** Get the count of unique architecture clock domains.
|
||||
|
||||
Enumerates all GIC CPU interfaces and returns the number of unique clock
|
||||
proximity domain IDs in the system.
|
||||
|
||||
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
|
||||
Protocol.
|
||||
@param [out] ClockDomainCount On success, the cardinal count of unique
|
||||
clock domains.
|
||||
|
||||
@retval EFI_SUCCESS Operation completed successfully.
|
||||
@retval EFI_INVALID_PARAMETER A parameter is invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
|
||||
@retval Other Other EFI_STATUS error from called functions.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetArchClockDomainInfo (
|
||||
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
|
||||
OUT UINT32 *ClockDomainCount
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 ProximityDomain;
|
||||
UINT32 CmCount;
|
||||
UINT32 Index;
|
||||
UINT32 UniqueIndex;
|
||||
CM_ARM_GICC_INFO *CmGiccInfo;
|
||||
UINT32 *ClockDomains;
|
||||
UINT32 UniqueCount;
|
||||
BOOLEAN IsUnique;
|
||||
|
||||
if ((CfgMgrProtocol == NULL) ||
|
||||
(ClockDomainCount == NULL))
|
||||
{
|
||||
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CmGiccInfo = NULL;
|
||||
ClockDomains = NULL;
|
||||
UniqueCount = 0;
|
||||
CmCount = 0;
|
||||
|
||||
Status = GetEArmObjGicCInfo (
|
||||
CfgMgrProtocol,
|
||||
CM_NULL_TOKEN,
|
||||
&CmGiccInfo,
|
||||
&CmCount
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"ERROR: MSCT: Failed to get GICC Info. Status = %r\n",
|
||||
Status
|
||||
));
|
||||
return Status;
|
||||
}
|
||||
|
||||
if ((CmGiccInfo == NULL) || (CmCount == 0)) {
|
||||
*ClockDomainCount = 0;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
// Allocate worst-case storage: every CPU could be in its own clock domain.
|
||||
ClockDomains = AllocateZeroPool (sizeof (UINT32) * CmCount);
|
||||
if (ClockDomains == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < CmCount; Index++) {
|
||||
Status = GetProximityDomainId (
|
||||
CfgMgrProtocol,
|
||||
CmGiccInfo[Index].ClockDomain,
|
||||
CmGiccInfo[Index].ClockDomainToken,
|
||||
&ProximityDomain
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"ERROR: MSCT: Failed to get Clock Domain ID for index %d. Status = %r\n",
|
||||
Index,
|
||||
Status
|
||||
));
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
goto error_handler;
|
||||
}
|
||||
|
||||
// Record the proximity domain ID only if not already seen.
|
||||
IsUnique = TRUE;
|
||||
for (UniqueIndex = 0; UniqueIndex < UniqueCount; UniqueIndex++) {
|
||||
if (ClockDomains[UniqueIndex] == ProximityDomain) {
|
||||
IsUnique = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsUnique) {
|
||||
ClockDomains[UniqueCount++] = ProximityDomain;
|
||||
}
|
||||
}
|
||||
|
||||
*ClockDomainCount = UniqueCount;
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
error_handler:
|
||||
if (ClockDomains != NULL) {
|
||||
FreePool (ClockDomains);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/** @file
|
||||
Default (stub) arch-specific ACPI MSCT Generator implementation.
|
||||
|
||||
Used for architectures that do not provide processor or clock domain
|
||||
information via the Configuration Manager (e.g. RISCV64, LOONGARCH64).
|
||||
Both functions return EFI_NOT_FOUND so that the common generator
|
||||
gracefully omits the arch-specific topology data from the MSCT.
|
||||
|
||||
Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
|
||||
// Module specific include files.
|
||||
#include <AcpiTableGenerator.h>
|
||||
#include <ConfigurationManagerObject.h>
|
||||
#include <Protocol/ConfigurationManagerProtocol.h>
|
||||
|
||||
#include "MsctGenerator.h"
|
||||
|
||||
/** Get architecture processor domain information.
|
||||
|
||||
This stub implementation returns EFI_NOT_FOUND for architectures that
|
||||
do not provide processor proximity domain data via the Configuration Manager.
|
||||
|
||||
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
|
||||
Protocol.
|
||||
@param [out] ProcDomainInfo Pointer to the processor domain information.
|
||||
@param [out] ProcDomainInfoCount Pointer to the count of processor domain
|
||||
information structures.
|
||||
|
||||
@retval EFI_NOT_FOUND Not supported on this architecture.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetArchProcessorDomainInfo (
|
||||
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
|
||||
OUT UINT32 **ProcDomainInfo,
|
||||
OUT UINT32 *ProcDomainInfoCount
|
||||
)
|
||||
{
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/** Get the count of unique architecture clock domains.
|
||||
|
||||
This stub implementation returns EFI_NOT_FOUND for architectures that
|
||||
do not provide clock domain data via the Configuration Manager.
|
||||
|
||||
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
|
||||
Protocol.
|
||||
@param [out] ClockDomainCount On success, the cardinal count of unique
|
||||
clock domains.
|
||||
|
||||
@retval EFI_NOT_FOUND Not supported on this architecture.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetArchClockDomainInfo (
|
||||
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
|
||||
OUT UINT32 *ClockDomainCount
|
||||
)
|
||||
{
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
1092
DynamicTablesPkg/Library/Acpi/Common/AcpiMsctLib/MsctGenerator.c
Normal file
1092
DynamicTablesPkg/Library/Acpi/Common/AcpiMsctLib/MsctGenerator.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,52 @@
|
|||
/** @file
|
||||
ACPI Maximum System Characteristics Table (MSCT) Generator header file.
|
||||
|
||||
Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
/** Get architecture processor domain information.
|
||||
|
||||
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
|
||||
Protocol.
|
||||
@param [out] ProcDomainInfo Pointer to the processor domain information.
|
||||
@param [out] ProcDomainInfoCount Pointer to the count of processor domain
|
||||
information structures.
|
||||
|
||||
@retval EFI_SUCCESS Operation completed successfully.
|
||||
@retval EFI_INVALID_PARAMETER A parameter is invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
|
||||
@retval Other Other EFI_STATUS error from called functions.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetArchProcessorDomainInfo (
|
||||
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
|
||||
OUT UINT32 **ProcDomainInfo,
|
||||
OUT UINT32 *ProcDomainInfoCount
|
||||
);
|
||||
|
||||
/** Get the count of unique architecture clock domains.
|
||||
|
||||
Enumerates all CPU interfaces and returns the number of unique clock
|
||||
proximity domain IDs in the system.
|
||||
|
||||
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
|
||||
Protocol.
|
||||
@param [out] ClockDomainCount On success, the cardinal count of unique
|
||||
clock domains.
|
||||
|
||||
@retval EFI_SUCCESS Operation completed successfully.
|
||||
@retval EFI_INVALID_PARAMETER A parameter is invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
|
||||
@retval Other Other EFI_STATUS error from called functions.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetArchClockDomainInfo (
|
||||
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
|
||||
OUT UINT32 *ClockDomainCount
|
||||
);
|
||||
|
|
@ -0,0 +1,249 @@
|
|||
/** @file
|
||||
X64 specific ACPI Maximum System Characteristics Table (MSCT) Generator
|
||||
|
||||
Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
|
||||
// Module specific include files.
|
||||
#include <AcpiTableGenerator.h>
|
||||
#include <ConfigurationManagerObject.h>
|
||||
#include <ConfigurationManagerHelper.h>
|
||||
#include <Library/TableHelperLib.h>
|
||||
#include <Protocol/ConfigurationManagerProtocol.h>
|
||||
#include <Library/CmObjHelperLib.h>
|
||||
|
||||
#include "MsctGenerator.h"
|
||||
|
||||
/**
|
||||
This macro is used to get the object information for the Local APIC X2APIC
|
||||
Affinity object.
|
||||
*/
|
||||
GET_OBJECT_LIST (
|
||||
EObjNameSpaceX64,
|
||||
EX64ObjLocalApicX2ApicAffinityInfo,
|
||||
CM_X64_LOCAL_APIC_X2APIC_AFFINITY_INFO
|
||||
);
|
||||
|
||||
/** Get architecture processor domain information.
|
||||
|
||||
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
|
||||
Protocol.
|
||||
@param [out] ProcDomainInfo Pointer to the processor domain information.
|
||||
@param [out] ProcDomainInfoCount Pointer to the count of processor domain
|
||||
information structures.
|
||||
|
||||
@retval EFI_SUCCESS Operation completed successfully.
|
||||
@retval EFI_INVALID_PARAMETER A parameter is invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
|
||||
@retval Other Other EFI_STATUS error from called functions.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetArchProcessorDomainInfo (
|
||||
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
|
||||
OUT UINT32 **ProcDomainInfo,
|
||||
OUT UINT32 *ProcDomainInfoCount
|
||||
)
|
||||
{
|
||||
CM_X64_LOCAL_APIC_X2APIC_AFFINITY_INFO *CmProcDomain;
|
||||
EFI_STATUS Status;
|
||||
UINT32 Index;
|
||||
UINT32 ProcDomainCount;
|
||||
UINT32 *ProcDomain;
|
||||
|
||||
if ((CfgMgrProtocol == NULL) ||
|
||||
(ProcDomainInfo == NULL) ||
|
||||
(ProcDomainInfoCount == NULL))
|
||||
{
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CmProcDomain = NULL;
|
||||
ProcDomain = NULL;
|
||||
ProcDomainCount = 0;
|
||||
Status = GetEX64ObjLocalApicX2ApicAffinityInfo (
|
||||
CfgMgrProtocol,
|
||||
CM_NULL_TOKEN,
|
||||
&CmProcDomain,
|
||||
&ProcDomainCount
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"MSCT: Failed to get processor affinity information. Status = %r\n",
|
||||
Status
|
||||
));
|
||||
goto error_handler;
|
||||
}
|
||||
|
||||
if ((ProcDomainCount == 0) || (CmProcDomain == NULL)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"MSCT: No Local Apic/X2Apic Affinity information found.\n"
|
||||
));
|
||||
Status = EFI_NOT_FOUND;
|
||||
goto error_handler;
|
||||
}
|
||||
|
||||
ProcDomain = AllocateZeroPool (
|
||||
sizeof (UINT32) *
|
||||
ProcDomainCount
|
||||
);
|
||||
if (ProcDomain == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto error_handler;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < ProcDomainCount; Index++) {
|
||||
Status = GetProximityDomainId (
|
||||
CfgMgrProtocol,
|
||||
CmProcDomain[Index].ProximityDomain,
|
||||
CmProcDomain[Index].ProximityDomainToken,
|
||||
&ProcDomain[Index]
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"MSCT: Failed to get Proximity Domain ID for index %d. Status = %r\n",
|
||||
Index,
|
||||
Status
|
||||
));
|
||||
goto error_handler;
|
||||
}
|
||||
}
|
||||
|
||||
*ProcDomainInfo = ProcDomain;
|
||||
*ProcDomainInfoCount = ProcDomainCount;
|
||||
return EFI_SUCCESS;
|
||||
|
||||
error_handler:
|
||||
if (ProcDomain != NULL) {
|
||||
FreePool (ProcDomain);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/** Get the count of unique architecture clock domains.
|
||||
|
||||
Enumerates all Local APIC/X2APIC affinity entries and returns the number of
|
||||
unique clock proximity domain IDs in the system.
|
||||
|
||||
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
|
||||
Protocol.
|
||||
@param [out] ClockDomainCount On success, the cardinal count of unique
|
||||
clock domains.
|
||||
|
||||
@retval EFI_SUCCESS Operation completed successfully.
|
||||
@retval EFI_INVALID_PARAMETER A parameter is invalid.
|
||||
@retval EFI_NOT_FOUND No affinity information was found.
|
||||
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
|
||||
@retval Other Other EFI_STATUS error from called functions.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetArchClockDomainInfo (
|
||||
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
|
||||
OUT UINT32 *ClockDomainCount
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 ProximityDomain;
|
||||
UINT32 CmCount;
|
||||
UINT32 Index;
|
||||
UINT32 UniqueIndex;
|
||||
UINT32 UniqueCount;
|
||||
UINT32 *ClockDomains;
|
||||
BOOLEAN IsUnique;
|
||||
CM_X64_LOCAL_APIC_X2APIC_AFFINITY_INFO *CmX2ApicAffinity;
|
||||
|
||||
if ((CfgMgrProtocol == NULL) ||
|
||||
(ClockDomainCount == NULL))
|
||||
{
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CmX2ApicAffinity = NULL;
|
||||
ClockDomains = NULL;
|
||||
UniqueCount = 0;
|
||||
CmCount = 0;
|
||||
|
||||
Status = GetEX64ObjLocalApicX2ApicAffinityInfo (
|
||||
CfgMgrProtocol,
|
||||
CM_NULL_TOKEN,
|
||||
&CmX2ApicAffinity,
|
||||
&CmCount
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"ERROR: MSCT: Failed to get Local Apic/X2Apic Affinity Info. Status = %r\n",
|
||||
Status
|
||||
));
|
||||
return Status;
|
||||
}
|
||||
|
||||
if ((CmX2ApicAffinity == NULL) || (CmCount == 0)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"ERROR: MSCT: Local Apic/X2Apic Affinity information not provided.\n"
|
||||
));
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Allocate worst-case storage: every CPU could be in its own clock domain.
|
||||
ClockDomains = AllocateZeroPool (sizeof (UINT32) * CmCount);
|
||||
if (ClockDomains == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < CmCount; Index++) {
|
||||
Status = GetProximityDomainId (
|
||||
CfgMgrProtocol,
|
||||
CmX2ApicAffinity[Index].ClockDomain,
|
||||
CmX2ApicAffinity[Index].ClockDomainToken,
|
||||
&ProximityDomain
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"ERROR: MSCT: Failed to get Clock Domain ID for index %d. Status = %r\n",
|
||||
Index,
|
||||
Status
|
||||
));
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
goto error_handler;
|
||||
}
|
||||
|
||||
// Record the proximity domain ID only if not already seen.
|
||||
IsUnique = TRUE;
|
||||
for (UniqueIndex = 0; UniqueIndex < UniqueCount; UniqueIndex++) {
|
||||
if (ClockDomains[UniqueIndex] == ProximityDomain) {
|
||||
IsUnique = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsUnique) {
|
||||
ClockDomains[UniqueCount++] = ProximityDomain;
|
||||
}
|
||||
}
|
||||
|
||||
*ClockDomainCount = UniqueCount;
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
error_handler:
|
||||
if (ClockDomains != NULL) {
|
||||
FreePool (ClockDomains);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue