DynamicTablesPkg: AcpiSsdtCpuTopologyLib: Avoid dependency on GICC

The GICC is an ARM specific structure. Other architectures have different
local interrupt controller structures from which CPU topology can be
created. Avoid the GICC reference in common code by:
- creating a wrapper CreateTopologyFromIntC() instead of
  CreateTopologyFromGicC() so that different archs can implement
  it differently.
- implementing arch specific functions to get the AcpiProcessorUid,
  CpcToken, EtToken and use them instead of using the GicC CM object
  directly.

Suggested-by: Sunil V L <sunilvl@ventanamicro.com>
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
This commit is contained in:
Pierre Gondois 2024-06-10 14:00:00 +02:00 committed by mergify[bot]
parent c6e0eed072
commit dfd867bd83
4 changed files with 647 additions and 301 deletions

View File

@ -0,0 +1,408 @@
/** @file
ARM SSDT Cpu Topology Table Generator Helpers.
Copyright (c) 2021 - 2023, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Reference(s):
- ACPI 6.3 Specification - January 2019 - s8.4 Declaring Processors
- ACPI for CoreSight version 1.2 Platform Design Document
(https://developer.arm.com/documentation/den0067/a/?lang=en)
@par Glossary:
- ETE - Embedded Trace Extension.
- ETM - Embedded Trace Macrocell.
**/
#include <Library/AcpiLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Protocol/AcpiTable.h>
// Module specific include files.
#include <AcpiTableGenerator.h>
#include <ConfigurationManagerObject.h>
#include <ConfigurationManagerHelper.h>
#include <Library/AcpiHelperLib.h>
#include <Library/TableHelperLib.h>
#include <Library/AmlLib/AmlLib.h>
#include <Protocol/ConfigurationManagerProtocol.h>
#include "SsdtCpuTopologyGenerator.h"
/** ARM SSDT Cpu Topology Table Generator.
Requirements:
The following Configuration Manager Object(s) are required by
this Generator:
- EArmObjGicCInfo
- EArmObjEtInfo (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
);
/**
This macro expands to a function that retrieves the ET device
information from the Configuration Manager.
*/
GET_OBJECT_LIST (
EObjNameSpaceArm,
EArmObjEtInfo,
CM_ARM_ET_INFO
);
/** Create an embedded trace device and add it to the Cpu Node in the
AML namespace.
This generates the following ASL code:
Device (E002)
{
Name (_UID, 2)
Name (_HID, "ARMHC500")
}
Note: Currently we only support generating ETE nodes. Unlike ETM,
ETE has a system register interface and therefore does not need
the MMIO range to be described.
@param [in] Generator The SSDT Cpu Topology generator.
@param [in] ParentNode Parent node to attach the Cpu node to.
@param [in] AcpiProcessorUid ACPI Processor UID of the CPU.
@param [in] CpuName Value used to generate the node name.
@param [out] EtNodePtr If not NULL, return the created Cpu node.
@retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/
STATIC
EFI_STATUS
EFIAPI
CreateAmlEtd (
IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
IN AML_NODE_HANDLE ParentNode,
IN UINT32 AcpiProcessorUid,
IN UINT32 CpuName,
OUT AML_OBJECT_NODE_HANDLE *EtNodePtr OPTIONAL
)
{
EFI_STATUS Status;
AML_OBJECT_NODE_HANDLE EtNode;
CHAR8 AslName[AML_NAME_SEG_SIZE + 1];
ASSERT (Generator != NULL);
ASSERT (ParentNode != NULL);
Status = WriteAslName ('E', CpuName, AslName);
if (EFI_ERROR (Status)) {
ASSERT (0);
return Status;
}
Status = AmlCodeGenDevice (AslName, ParentNode, &EtNode);
if (EFI_ERROR (Status)) {
ASSERT (0);
return Status;
}
Status = AmlCodeGenNameInteger (
"_UID",
AcpiProcessorUid,
EtNode,
NULL
);
if (EFI_ERROR (Status)) {
ASSERT (0);
return Status;
}
Status = AmlCodeGenNameString (
"_HID",
ACPI_HID_ET_DEVICE,
EtNode,
NULL
);
if (EFI_ERROR (Status)) {
ASSERT (0);
return Status;
}
// If requested, return the handle to the EtNode.
if (EtNodePtr != NULL) {
*EtNodePtr = EtNode;
}
return Status;
}
/** Create and add an Embedded trace device to the Cpu Node.
@param [in] Generator The SSDT Cpu Topology generator.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
@param [in] AcpiProcessorUid ACPI processor Uid of the local intc (gicc, other)
describing the Cpu.
@param [in] EtToken Embedded Trace Token of the CPU.
@param [in] CpuName Value used to generate the CPU node name.
@param [in] CpuNode CPU Node to which the ET device node is
attached.
@retval EFI_SUCCESS The function completed successfully.
@retval EFI_UNSUPPORTED Feature Unsupported.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/
STATIC
EFI_STATUS
EFIAPI
CreateAmlEtNode (
IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
IN UINT32 AcpiProcessorUid,
IN CM_OBJECT_TOKEN EtToken,
IN UINT32 CpuName,
IN AML_OBJECT_NODE_HANDLE *CpuNode
)
{
EFI_STATUS Status;
CM_ARM_ET_INFO *EtInfo;
Status = GetEArmObjEtInfo (
CfgMgrProtocol,
EtToken,
&EtInfo,
NULL
);
if (EFI_ERROR (Status)) {
ASSERT (0);
return Status;
}
// Currently we only support creation of a ETE Node.
if (EtInfo->EtType != ArmEtTypeEte) {
return EFI_UNSUPPORTED;
}
Status = CreateAmlEtd (
Generator,
CpuNode,
AcpiProcessorUid,
CpuName,
NULL
);
ASSERT_EFI_ERROR (Status);
return Status;
}
/** Create the processor hierarchy AML tree from arch specific CM objects.
The Arm architecture will use the CM_ARM_GICC_INFO CM objects for instance.
A processor container is by extension any non-leave device in the cpu topology.
@param [in] Generator The SSDT Cpu Topology generator.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
@param [in] ScopeNode Scope node handle ('\_SB' scope).
@retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/
EFI_STATUS
EFIAPI
CreateTopologyFromIntC (
IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
IN AML_OBJECT_NODE_HANDLE ScopeNode
)
{
EFI_STATUS Status;
CM_ARM_GICC_INFO *GicCInfo;
UINT32 GicCInfoCount;
UINT32 Index;
AML_OBJECT_NODE_HANDLE CpuNode;
ASSERT (Generator != NULL);
ASSERT (CfgMgrProtocol != NULL);
ASSERT (ScopeNode != NULL);
Status = GetEArmObjGicCInfo (
CfgMgrProtocol,
CM_NULL_TOKEN,
&GicCInfo,
&GicCInfoCount
);
if (EFI_ERROR (Status)) {
ASSERT (0);
return Status;
}
// For each CM_ARM_GICC_INFO object, create an AML node.
for (Index = 0; Index < GicCInfoCount; Index++) {
Status = CreateAmlCpu (
Generator,
ScopeNode,
GicCInfo[Index].AcpiProcessorUid,
Index,
&CpuNode
);
if (EFI_ERROR (Status)) {
ASSERT (0);
break;
}
// If a CPC info is associated with the
// GicCinfo, create an _CPC method returning them.
if (GicCInfo[Index].CpcToken != CM_NULL_TOKEN) {
Status = CreateAmlCpcNode (Generator, CfgMgrProtocol, GicCInfo[Index].CpcToken, CpuNode);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
break;
}
}
if (GicCInfo[Index].EtToken != CM_NULL_TOKEN) {
Status = CreateAmlEtNode (
Generator,
CfgMgrProtocol,
GicCInfo[Index].AcpiProcessorUid,
GicCInfo[Index].EtToken,
Index,
CpuNode
);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
return Status;
}
}
} // for
return Status;
}
/** Get generic interrupt information from arch specific CM objects.
The AcpiProcessorUid, CpcToken, etc. are held in arch specific CM objects,
in the CM_ARM_GICC_INFO CM object for Arm for instance.
This wrapper allows to get this information from each arch object.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
@param [in] AcpiIdObjectToken AcpiIdObjectToken identifying the CPU to fetch the
other fields from.
@param [out] AcpiProcessorUid AcpiProcessorUid of the CPU identified by
the AcpiIdObjectToken.
@param [out] CpcToken CpcToken of the CPU identified by
the AcpiIdObjectToken.
@param [out] PsdToken PsdToken of the CPU identified by
the AcpiIdObjectToken.
@retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_NOT_FOUND Not found.
**/
EFI_STATUS
EFIAPI
GetIntCInfo (
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
IN CM_OBJECT_TOKEN AcpiIdObjectToken,
OUT UINT32 *AcpiProcessorUid,
OUT CM_OBJECT_TOKEN *CpcToken,
OUT CM_OBJECT_TOKEN *PsdToken
)
{
EFI_STATUS Status;
CM_ARM_GICC_INFO *GicCInfo;
Status = GetEArmObjGicCInfo (
CfgMgrProtocol,
AcpiIdObjectToken,
&GicCInfo,
NULL
);
if (EFI_ERROR (Status)) {
return Status;
}
if (AcpiProcessorUid != NULL) {
*AcpiProcessorUid = GicCInfo->AcpiProcessorUid;
}
if (CpcToken != NULL) {
*CpcToken = GicCInfo->CpcToken;
}
if (PsdToken != NULL) {
*PsdToken = GicCInfo->PsdToken;
}
return Status;
}
/** Add arch specific information to a CPU node in the asl description.
@param [in] Generator The SSDT Cpu Topology generator.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
@param [in] AcpiIdObjectToken AcpiIdObjectToken identifying the CPU to fetch the
other fields from.
@param [in] CpuName Value used to generate the CPU node name.
@param [out] CpuNode CPU Node to which the ET device node is
attached.
@retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_NOT_FOUND Not found.
@retval EFI_UNSUPPORTED Feature Unsupported.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/
EFI_STATUS
EFIAPI
AddArchAmlCpuInfo (
IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
IN CM_OBJECT_TOKEN AcpiIdObjectToken,
IN UINT32 CpuName,
OUT AML_OBJECT_NODE_HANDLE *CpuNode
)
{
EFI_STATUS Status;
CM_ARM_GICC_INFO *GicCInfo;
Status = GetEArmObjGicCInfo (
CfgMgrProtocol,
AcpiIdObjectToken,
&GicCInfo,
NULL
);
if (EFI_ERROR (Status)) {
return Status;
}
// Add an Embedded Trace node if present.
if (GicCInfo->EtToken != CM_NULL_TOKEN) {
Status = CreateAmlEtNode (
Generator,
CfgMgrProtocol,
GicCInfo->AcpiProcessorUid,
GicCInfo->EtToken,
CpuName,
CpuNode
);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
return Status;
}
}
return Status;
}

View File

@ -32,28 +32,17 @@
#include "SsdtCpuTopologyGenerator.h" #include "SsdtCpuTopologyGenerator.h"
/** ARM standard SSDT Cpu Topology Table Generator. /** SSDT Cpu Topology Table Generator.
Requirements: Requirements:
The following Configuration Manager Object(s) are required by The following Configuration Manager Object(s) are required by
this Generator: this Generator:
- EArmObjGicCInfo
- EArchCommonObjProcHierarchyInfo (OPTIONAL) along with - EArchCommonObjProcHierarchyInfo (OPTIONAL) along with
- EArchCommonObjCmRef (OPTIONAL) - EArchCommonObjCmRef (OPTIONAL)
- EArchCommonObjLpiInfo (OPTIONAL) - EArchCommonObjLpiInfo (OPTIONAL)
- GetEArmObjEtInfo (OPTIONAL)
- EArchCommonObjPsdInfo (OPTIONAL) - EArchCommonObjPsdInfo (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
);
/** /**
This macro expands to a function that retrieves the Processor Hierarchy This macro expands to a function that retrieves the Processor Hierarchy
information from the Configuration Manager. information from the Configuration Manager.
@ -94,16 +83,6 @@ GET_OBJECT_LIST (
CM_ARCH_COMMON_CPC_INFO CM_ARCH_COMMON_CPC_INFO
); );
/**
This macro expands to a function that retrieves the ET device
information from the Configuration Manager.
*/
GET_OBJECT_LIST (
EObjNameSpaceArm,
EArmObjEtInfo,
CM_ARM_ET_INFO
);
/** /**
This macro expands to a function that retrieves the PSD This macro expands to a function that retrieves the PSD
information from the Configuration Manager. information from the Configuration Manager.
@ -238,7 +217,6 @@ TokenTableAdd (
@retval EFI_SUCCESS Success. @retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter. @retval EFI_INVALID_PARAMETER Invalid parameter.
**/ **/
STATIC
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
WriteAslName ( WriteAslName (
@ -294,8 +272,7 @@ WriteAslName (
@param [in] Generator The SSDT Cpu Topology generator. @param [in] Generator The SSDT Cpu Topology generator.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager @param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface. Protocol Interface.
@param [in] GicCInfo Pointer to the CM_ARM_GICC_INFO object @param [in] PsdToken Token to identify the Psd information.
describing the Cpu.
@param [in] Node CPU Node to which the _CPC node is @param [in] Node CPU Node to which the _CPC node is
attached. attached.
@ -309,7 +286,7 @@ EFIAPI
CreateAmlPsdNode ( CreateAmlPsdNode (
IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
IN CM_ARM_GICC_INFO *GicCInfo, IN CM_OBJECT_TOKEN PsdToken,
IN AML_OBJECT_NODE_HANDLE *Node IN AML_OBJECT_NODE_HANDLE *Node
) )
{ {
@ -318,7 +295,7 @@ CreateAmlPsdNode (
Status = GetEArchCommonObjPsdInfo ( Status = GetEArchCommonObjPsdInfo (
CfgMgrProtocol, CfgMgrProtocol,
GicCInfo->PsdToken, PsdToken,
&PsdInfo, &PsdInfo,
NULL NULL
); );
@ -381,7 +358,7 @@ CreateAmlPsdNode (
@param [in] Generator The SSDT Cpu Topology generator. @param [in] Generator The SSDT Cpu Topology generator.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager @param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface. Protocol Interface.
@param [in] GicCInfo Pointer to the CM_ARM_GICC_INFO object @param [in] CpcToken CPC token of the INTC info
describing the Cpu. describing the Cpu.
@param [in] Node CPU Node to which the _CPC node is @param [in] Node CPU Node to which the _CPC node is
attached. attached.
@ -390,13 +367,12 @@ CreateAmlPsdNode (
@retval EFI_INVALID_PARAMETER Invalid parameter. @retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/ **/
STATIC
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
CreateAmlCpcNode ( CreateAmlCpcNode (
IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
IN CM_ARM_GICC_INFO *GicCInfo, IN CM_OBJECT_TOKEN CpcToken,
IN AML_OBJECT_NODE_HANDLE *Node IN AML_OBJECT_NODE_HANDLE *Node
) )
{ {
@ -405,7 +381,7 @@ CreateAmlCpcNode (
Status = GetEArchCommonObjCpcInfo ( Status = GetEArchCommonObjCpcInfo (
CfgMgrProtocol, CfgMgrProtocol,
GicCInfo->CpcToken, CpcToken,
&CpcInfo, &CpcInfo,
NULL NULL
); );
@ -423,147 +399,6 @@ CreateAmlCpcNode (
return Status; return Status;
} }
/** Create an embedded trace device and add it to the Cpu Node in the
AML namespace.
This generates the following ASL code:
Device (E002)
{
Name (_UID, 2)
Name (_HID, "ARMHC500")
}
Note: Currently we only support generating ETE nodes. Unlike ETM,
ETE has a system register interface and therefore does not need
the MMIO range to be described.
@param [in] Generator The SSDT Cpu Topology generator.
@param [in] ParentNode Parent node to attach the Cpu node to.
@param [in] GicCInfo CM_ARM_GICC_INFO object used to create the node.
@param [in] CpuName Value used to generate the node name.
@param [out] EtNodePtr If not NULL, return the created Cpu node.
@retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/
STATIC
EFI_STATUS
EFIAPI
CreateAmlEtd (
IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
IN AML_NODE_HANDLE ParentNode,
IN CM_ARM_GICC_INFO *GicCInfo,
IN UINT32 CpuName,
OUT AML_OBJECT_NODE_HANDLE *EtNodePtr OPTIONAL
)
{
EFI_STATUS Status;
AML_OBJECT_NODE_HANDLE EtNode;
CHAR8 AslName[AML_NAME_SEG_SIZE + 1];
ASSERT (Generator != NULL);
ASSERT (ParentNode != NULL);
Status = WriteAslName ('E', CpuName, AslName);
if (EFI_ERROR (Status)) {
ASSERT (0);
return Status;
}
Status = AmlCodeGenDevice (AslName, ParentNode, &EtNode);
if (EFI_ERROR (Status)) {
ASSERT (0);
return Status;
}
Status = AmlCodeGenNameInteger (
"_UID",
GicCInfo->AcpiProcessorUid,
EtNode,
NULL
);
if (EFI_ERROR (Status)) {
ASSERT (0);
return Status;
}
Status = AmlCodeGenNameString (
"_HID",
ACPI_HID_ET_DEVICE,
EtNode,
NULL
);
if (EFI_ERROR (Status)) {
ASSERT (0);
return Status;
}
// If requested, return the handle to the EtNode.
if (EtNodePtr != NULL) {
*EtNodePtr = EtNode;
}
return Status;
}
/** Create and add an Embedded trace device to the Cpu Node.
@param [in] Generator The SSDT Cpu Topology generator.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
@param [in] GicCInfo Pointer to the CM_ARM_GICC_INFO object
describing the Cpu.
@param [in] CpuName Value used to generate the CPU node name.
@param [in] Node CPU Node to which the ET device node is
attached.
@retval EFI_SUCCESS The function completed successfully.
@retval EFI_UNSUPPORTED Feature Unsupported.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/
STATIC
EFI_STATUS
EFIAPI
CreateAmlEtNode (
IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
IN CM_ARM_GICC_INFO *GicCInfo,
IN UINT32 CpuName,
IN AML_OBJECT_NODE_HANDLE *Node
)
{
EFI_STATUS Status;
CM_ARM_ET_INFO *EtInfo;
Status = GetEArmObjEtInfo (
CfgMgrProtocol,
GicCInfo->EtToken,
&EtInfo,
NULL
);
if (EFI_ERROR (Status)) {
ASSERT (0);
return Status;
}
// Currently we only support creation of a ETE Node.
if (EtInfo->EtType != ArmEtTypeEte) {
return EFI_UNSUPPORTED;
}
Status = CreateAmlEtd (
Generator,
Node,
GicCInfo,
CpuName,
NULL
);
ASSERT_EFI_ERROR (Status);
return Status;
}
/** Create and add an _LPI method to Cpu/Cluster Node. /** Create and add an _LPI method to Cpu/Cluster Node.
For instance, transform an AML node from: For instance, transform an AML node from:
@ -789,23 +624,22 @@ GenerateLpiStates (
Name (_HID, "ACPI0007") Name (_HID, "ACPI0007")
} }
@param [in] Generator The SSDT Cpu Topology generator. @param [in] Generator The SSDT Cpu Topology generator.
@param [in] ParentNode Parent node to attach the Cpu node to. @param [in] ParentNode Parent node to attach the Cpu node to.
@param [in] GicCInfo CM_ARM_GICC_INFO object used to create the node. @param [in] AcpiProcessorUid ACPI processor UID of the CPU.
@param [in] CpuName Value used to generate the node name. @param [in] CpuName Value used to generate the node name.
@param [out] CpuNodePtr If not NULL, return the created Cpu node. @param [out] CpuNodePtr If not NULL, return the created Cpu node.
@retval EFI_SUCCESS Success. @retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter. @retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/ **/
STATIC
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
CreateAmlCpu ( CreateAmlCpu (
IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
IN AML_NODE_HANDLE ParentNode, IN AML_NODE_HANDLE ParentNode,
IN CM_ARM_GICC_INFO *GicCInfo, IN UINT32 AcpiProcessorUid,
IN UINT32 CpuName, IN UINT32 CpuName,
OUT AML_OBJECT_NODE_HANDLE *CpuNodePtr OPTIONAL OUT AML_OBJECT_NODE_HANDLE *CpuNodePtr OPTIONAL
) )
@ -816,7 +650,6 @@ CreateAmlCpu (
ASSERT (Generator != NULL); ASSERT (Generator != NULL);
ASSERT (ParentNode != NULL); ASSERT (ParentNode != NULL);
ASSERT (GicCInfo != NULL);
Status = WriteAslName ('C', CpuName, AslName); Status = WriteAslName ('C', CpuName, AslName);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
@ -832,7 +665,7 @@ CreateAmlCpu (
Status = AmlCodeGenNameInteger ( Status = AmlCodeGenNameInteger (
"_UID", "_UID",
GicCInfo->AcpiProcessorUid, AcpiProcessorUid,
CpuNode, CpuNode,
NULL NULL
); );
@ -887,8 +720,10 @@ CreateAmlCpuFromProcHierarchy (
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
CM_ARM_GICC_INFO *GicCInfo;
AML_OBJECT_NODE_HANDLE CpuNode; AML_OBJECT_NODE_HANDLE CpuNode;
UINT32 AcpiProcessorUid;
CM_OBJECT_TOKEN CpcToken;
CM_OBJECT_TOKEN PsdToken;
ASSERT (Generator != NULL); ASSERT (Generator != NULL);
ASSERT (CfgMgrProtocol != NULL); ASSERT (CfgMgrProtocol != NULL);
@ -896,18 +731,19 @@ CreateAmlCpuFromProcHierarchy (
ASSERT (ProcHierarchyNodeInfo != NULL); ASSERT (ProcHierarchyNodeInfo != NULL);
ASSERT (ProcHierarchyNodeInfo->AcpiIdObjectToken != CM_NULL_TOKEN); ASSERT (ProcHierarchyNodeInfo->AcpiIdObjectToken != CM_NULL_TOKEN);
Status = GetEArmObjGicCInfo ( Status = GetIntCInfo (
CfgMgrProtocol, CfgMgrProtocol,
ProcHierarchyNodeInfo->AcpiIdObjectToken, ProcHierarchyNodeInfo->AcpiIdObjectToken,
&GicCInfo, &AcpiProcessorUid,
NULL &CpcToken,
&PsdToken
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
ASSERT (0); ASSERT (0);
return Status; return Status;
} }
Status = CreateAmlCpu (Generator, ParentNode, GicCInfo, CpuName, &CpuNode); Status = CreateAmlCpu (Generator, ParentNode, AcpiProcessorUid, CpuName, &CpuNode);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
ASSERT (0); ASSERT (0);
return Status; return Status;
@ -923,8 +759,8 @@ CreateAmlCpuFromProcHierarchy (
} }
} }
if (GicCInfo->PsdToken != CM_NULL_TOKEN) { if (PsdToken != CM_NULL_TOKEN) {
Status = CreateAmlPsdNode (Generator, CfgMgrProtocol, GicCInfo, CpuNode); Status = CreateAmlPsdNode (Generator, CfgMgrProtocol, PsdToken, CpuNode);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status); ASSERT_EFI_ERROR (Status);
return Status; return Status;
@ -932,28 +768,26 @@ CreateAmlCpuFromProcHierarchy (
} }
// If a CPC info is associated with the // If a CPC info is associated with the
// GicCinfo, create an _CPC method returning them. // IntcInfo, create an _CPC method returning them.
if (GicCInfo->CpcToken != CM_NULL_TOKEN) { if (CpcToken != CM_NULL_TOKEN) {
Status = CreateAmlCpcNode (Generator, CfgMgrProtocol, GicCInfo, CpuNode); Status = CreateAmlCpcNode (Generator, CfgMgrProtocol, CpcToken, CpuNode);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status); ASSERT_EFI_ERROR (Status);
return Status; return Status;
} }
} }
// Add an Embedded Trace node if present. // Add arch specific information if necessary.
if (GicCInfo->EtToken != CM_NULL_TOKEN) { Status = AddArchAmlCpuInfo (
Status = CreateAmlEtNode ( Generator,
Generator, CfgMgrProtocol,
CfgMgrProtocol, ProcHierarchyNodeInfo->AcpiIdObjectToken,
GicCInfo, CpuName,
CpuName, CpuNode
CpuNode );
); if (EFI_ERROR (Status)) {
if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status);
ASSERT_EFI_ERROR (Status); return Status;
return Status;
}
} }
return Status; return Status;
@ -1342,100 +1176,6 @@ exit_handler:
return Status; return Status;
} }
/** Create the processor hierarchy AML tree from CM_ARM_GICC_INFO
CM objects.
A processor container is by extension any non-leave device in the cpu topology.
@param [in] Generator The SSDT Cpu Topology generator.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
@param [in] ScopeNode Scope node handle ('\_SB' scope).
@retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/
STATIC
EFI_STATUS
EFIAPI
CreateTopologyFromGicC (
IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
IN AML_OBJECT_NODE_HANDLE ScopeNode
)
{
EFI_STATUS Status;
CM_ARM_GICC_INFO *GicCInfo;
UINT32 GicCInfoCount;
UINT32 Index;
AML_OBJECT_NODE_HANDLE CpuNode;
ASSERT (Generator != NULL);
ASSERT (CfgMgrProtocol != NULL);
ASSERT (ScopeNode != NULL);
Status = GetEArmObjGicCInfo (
CfgMgrProtocol,
CM_NULL_TOKEN,
&GicCInfo,
&GicCInfoCount
);
if (EFI_ERROR (Status)) {
ASSERT (0);
return Status;
}
// For each CM_ARM_GICC_INFO object, create an AML node.
for (Index = 0; Index < GicCInfoCount; Index++) {
Status = CreateAmlCpu (
Generator,
ScopeNode,
&GicCInfo[Index],
Index,
&CpuNode
);
if (EFI_ERROR (Status)) {
ASSERT (0);
break;
}
if (GicCInfo->PsdToken != CM_NULL_TOKEN) {
Status = CreateAmlPsdNode (Generator, CfgMgrProtocol, GicCInfo, CpuNode);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
return Status;
}
}
// If a CPC info is associated with the
// GicCinfo, create an _CPC method returning them.
if (GicCInfo[Index].CpcToken != CM_NULL_TOKEN) {
Status = CreateAmlCpcNode (Generator, CfgMgrProtocol, &GicCInfo[Index], CpuNode);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
break;
}
}
if (GicCInfo[Index].EtToken != CM_NULL_TOKEN) {
Status = CreateAmlEtNode (
Generator,
CfgMgrProtocol,
&GicCInfo[Index],
Index,
CpuNode
);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
return Status;
}
}
} // for
return Status;
}
/** Construct the SSDT Cpu Topology ACPI table. /** Construct the SSDT Cpu Topology ACPI table.
This function invokes the Configuration Manager protocol interface This function invokes the Configuration Manager protocol interface
@ -1514,9 +1254,8 @@ BuildSsdtCpuTopologyTable (
} }
if (Status == EFI_NOT_FOUND) { if (Status == EFI_NOT_FOUND) {
// If hierarchy information is not found generate a flat topology // If hierarchy information is not found generate a flat topology.
// using CM_ARM_GICC_INFO objects. Status = CreateTopologyFromIntC (
Status = CreateTopologyFromGicC (
Generator, Generator,
CfgMgrProtocol, CfgMgrProtocol,
ScopeNode ScopeNode

View File

@ -144,4 +144,200 @@ typedef struct AcpiCpuTopologyGenerator {
#pragma pack() #pragma pack()
/** Write a string 'Xxxx\0' in AslName (5 bytes long),
with 'X' being the leading char of the name, and
with 'xxx' being Value in hexadecimal.
As 'xxx' in hexadecimal represents a number on 12 bits,
we have Value < (1 << 12).
@param [in] LeadChar Leading char of the name.
@param [in] Value Hex value of the name.
Must be lower than (2 << 12).
@param [in, out] AslName Pointer to write the 'Xxxx' string to.
Must be at least 5 bytes long.
@retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter.
**/
EFI_STATUS
EFIAPI
WriteAslName (
IN CHAR8 LeadChar,
IN UINT32 Value,
IN OUT CHAR8 *AslName
);
/** Get generic interrupt information from arch specific CM objects.
The AcpiProcessorUid, CpcToken, etc. are held in arch specific CM objects,
in the CM_ARM_GICC_INFO CM object for Arm for instance.
This wrapper allows to get this information from each arch object.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
@param [in] AcpiProcessorUid ACPI processor Uid of the local intc (gicc, other)
other fields from.
@param [out] AcpiProcessorUid AcpiProcessorUid of the CPU identified by
the AcpiIdObjectToken.
@param [out] CpcToken CpcToken of the CPU identified by
the AcpiIdObjectToken.
@param [out] PsdToken PsdToken of the CPU identified by
the AcpiIdObjectToken.
@retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_NOT_FOUND Not found.
**/
EFI_STATUS
EFIAPI
GetIntCInfo (
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
IN CM_OBJECT_TOKEN AcpiIdObjectToken,
OUT UINT32 *AcpiProcessorUid,
OUT CM_OBJECT_TOKEN *CpcToken,
OUT CM_OBJECT_TOKEN *PsdToken
);
/** Create and add an _CPC Node to Cpu Node.
For instance, transform an AML node from:
Device (C002)
{
Name (_UID, 2)
Name (_HID, "ACPI0007")
}
To:
Device (C002)
{
Name (_UID, 2)
Name (_HID, "ACPI0007")
Name(_CPC, Package()
{
NumEntries, // Integer
Revision, // Integer
HighestPerformance, // Integer or Buffer (Resource Descriptor)
NominalPerformance, // Integer or Buffer (Resource Descriptor)
LowestNonlinearPerformance, // Integer or Buffer (Resource Descriptor)
LowestPerformance, // Integer or Buffer (Resource Descriptor)
GuaranteedPerformanceRegister, // Buffer (Resource Descriptor)
DesiredPerformanceRegister , // Buffer (Resource Descriptor)
MinimumPerformanceRegister , // Buffer (Resource Descriptor)
MaximumPerformanceRegister , // Buffer (Resource Descriptor)
PerformanceReductionToleranceRegister, // Buffer (Resource Descriptor)
TimeWindowRegister, // Buffer (Resource Descriptor)
CounterWraparoundTime, // Integer or Buffer (Resource Descriptor)
ReferencePerformanceCounterRegister, // Buffer (Resource Descriptor)
DeliveredPerformanceCounterRegister, // Buffer (Resource Descriptor)
PerformanceLimitedRegister, // Buffer (Resource Descriptor)
CPPCEnableRegister // Buffer (Resource Descriptor)
AutonomousSelectionEnable, // Integer or Buffer (Resource Descriptor)
AutonomousActivityWindowRegister, // Buffer (Resource Descriptor)
EnergyPerformancePreferenceRegister, // Buffer (Resource Descriptor)
ReferencePerformance // Integer or Buffer (Resource Descriptor)
LowestFrequency, // Integer or Buffer (Resource Descriptor)
NominalFrequency // Integer or Buffer (Resource Descriptor)
})
}
@param [in] Generator The SSDT Cpu Topology generator.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
@param [in] CpcToken CPC token of the INTC info
describing the Cpu.
@param [in] Node CPU Node to which the _CPC node is
attached.
@retval EFI_SUCCESS The function completed successfully.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/
EFI_STATUS
EFIAPI
CreateAmlCpcNode (
IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
IN CM_OBJECT_TOKEN CpcToken,
IN AML_OBJECT_NODE_HANDLE *Node
);
/** Create a Cpu in the AML namespace.
This generates the following ASL code:
Device (C002)
{
Name (_UID, 2)
Name (_HID, "ACPI0007")
}
@param [in] Generator The SSDT Cpu Topology generator.
@param [in] ParentNode Parent node to attach the Cpu node to.
@param [in] AcpiProcessorUid ACPI processor UID of the CPU.
@param [in] CpuName Value used to generate the node name.
@param [out] CpuNodePtr If not NULL, return the created Cpu node.
@retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/
EFI_STATUS
EFIAPI
CreateAmlCpu (
IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
IN AML_NODE_HANDLE ParentNode,
IN UINT32 AcpiProcessorUid,
IN UINT32 CpuName,
OUT AML_OBJECT_NODE_HANDLE *CpuNodePtr OPTIONAL
);
/** Create the processor hierarchy AML tree from arch specific CM objects.
The Arm architecture will use the CM_ARM_GICC_INFO CM objects for instance.
A processor container is by extension any non-leave device in the cpu topology.
@param [in] Generator The SSDT Cpu Topology generator.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
@param [in] ScopeNode Scope node handle ('\_SB' scope).
@retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/
EFI_STATUS
EFIAPI
CreateTopologyFromIntC (
IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
IN AML_OBJECT_NODE_HANDLE ScopeNode
);
/** Add arch specific information to a CPU node in the asl description.
@param [in] Generator The SSDT Cpu Topology generator.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
@param [in] AcpiIdObjectToken AcpiIdObjectToken identifying the CPU to fetch the
other fields from.
@param [in] CpuName Value used to generate the CPU node name.
@param [out] CpuNode CPU Node to which the ET device node is
attached.
@retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_NOT_FOUND Not found.
@retval EFI_UNSUPPORTED Feature Unsupported.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/
EFI_STATUS
EFIAPI
AddArchAmlCpuInfo (
IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
IN CM_OBJECT_TOKEN AcpiIdObjectToken,
IN UINT32 CpuName,
OUT AML_OBJECT_NODE_HANDLE *CpuNode
);
#endif // SSDT_CPU_TOPOLOGY_GENERATOR_H_ #endif // SSDT_CPU_TOPOLOGY_GENERATOR_H_

View File

@ -20,6 +20,9 @@
SsdtCpuTopologyGenerator.c SsdtCpuTopologyGenerator.c
SsdtCpuTopologyGenerator.h SsdtCpuTopologyGenerator.h
[Sources.ARM, Sources.AARCH64]
Arm/ArmSsdtCpuTopologyGenerator.c
[Packages.ARM, Packages.AARCH64] [Packages.ARM, Packages.AARCH64]
ArmPlatformPkg/ArmPlatformPkg.dec ArmPlatformPkg/ArmPlatformPkg.dec