mirror of
https://github.com/tianocore/edk2.git
synced 2025-08-31 05:18:36 +00:00

The ACPI specification v6.5, sTable 5.158: Processor Structure Flags states that: """ The processor container will have a matching ID value returned through the _UID method. As not every pro- cessor hierarchy node structure in PPTT may have a matching processor container, this flag indicates whether the ACPI pro- cessor ID points to valid entry. Where a valid entry is possible the ACPI Processor ID and _UID method are mandatory. """ And in: Table 5.157: Processor Hierarchy Node Structure """ If the processor structure rep- resents a group of associated processors, the structure might match a processor container in the name space. In that case this entry will match the value of the _UID method of the as- sociated processor container. Where there is a match it must be represented. The flags field, described in Processor Struc- ture Flags, includes a bit to describe whether the ACPI pro- cessor ID is valid. """ The DynamicTablesPkg currently creates a processor container: - in the SSDT CPU Topology generator, with the _HID=ACPI0010, and with a valid _UID - in the PPTT table for each CM_ARCH_COMMON_PROC_HIERARCHY_INFO structure. Thus: - all the processor containers should have the VALID bit set if the SSDT CPU Topology table is present. - if the SSDT CPU Topology table is present, but there is no PPTT table, then the state of the VALID bit is ignored. A contrario, an example where the VALID bit should not be set would be if: - the SSDT CPU Topology generator is absent - no processor container is created in the SSDT topology, i.e. if a flat hierarchy is created. Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
402 lines
16 KiB
C
402 lines
16 KiB
C
/** @file
|
|
SSDT Cpu Topology Table Generator.
|
|
|
|
Copyright (c) 2021 - 2023, Arm Limited. All rights reserved.<BR>
|
|
Copyright (C) 2025, Advanced Micro Devices, Inc. All rights reserved.
|
|
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.
|
|
**/
|
|
|
|
#ifndef SSDT_CPU_TOPOLOGY_GENERATOR_H_
|
|
#define SSDT_CPU_TOPOLOGY_GENERATOR_H_
|
|
|
|
#pragma pack(1)
|
|
|
|
// Mask for the flags that need to be checked.
|
|
#define PPTT_PROCESSOR_MASK ( \
|
|
(EFI_ACPI_6_3_PPTT_PACKAGE_PHYSICAL) | \
|
|
(EFI_ACPI_6_3_PPTT_PROCESSOR_ID_VALID << 1) | \
|
|
(EFI_ACPI_6_3_PPTT_NODE_IS_LEAF << 3))
|
|
|
|
// Mask for the cpu flags.
|
|
#define PPTT_CPU_PROCESSOR_MASK ( \
|
|
(EFI_ACPI_6_3_PPTT_PACKAGE_NOT_PHYSICAL) | \
|
|
(EFI_ACPI_6_3_PPTT_PROCESSOR_ID_VALID << 1) | \
|
|
(EFI_ACPI_6_3_PPTT_NODE_IS_LEAF << 3))
|
|
|
|
// Mask for the cluster flags.
|
|
// Even though a _UID is generated for clusters, it is simpler to use
|
|
// EFI_ACPI_6_3_PPTT_PROCESSOR_ID_INVALID and to not match the cluster id of
|
|
// the PPTT table (not sure the PPTT table is generated).
|
|
#define PPTT_CLUSTER_PROCESSOR_MASK ( \
|
|
(EFI_ACPI_6_3_PPTT_PACKAGE_NOT_PHYSICAL) | \
|
|
(EFI_ACPI_6_3_PPTT_PROCESSOR_ID_INVALID << 1) | \
|
|
(EFI_ACPI_6_3_PPTT_NODE_IS_NOT_LEAF << 3))
|
|
|
|
// Mask for the VALID flag.
|
|
#define PPTT_VALID_FLAG_MASK (EFI_ACPI_6_3_PPTT_PROCESSOR_ID_VALID << 1)
|
|
|
|
// Mask for the LEAF flag.
|
|
#define PPTT_LEAF_FLAG_MASK (EFI_ACPI_6_3_PPTT_NODE_IS_LEAF << 3)
|
|
|
|
/** LPI states are stored in the ASL namespace at '\_SB_.Lxxx',
|
|
with xxx being the node index of the LPI state.
|
|
*/
|
|
#define SB_SCOPE "\\_SB_"
|
|
#define SB_SCOPE_PREFIX SB_SCOPE "."
|
|
/// Size of the SB_SCOPE_PREFIX string.
|
|
#define SB_SCOPE_PREFIX_SIZE sizeof (SB_SCOPE_PREFIX)
|
|
|
|
/** C-state are stored in the ASL namspace at '\_SB_.CSTS.Cxxx',
|
|
where xxx represents the C-state index:
|
|
CSTx - for C-state indices less than 0xF.
|
|
CSxx - for C-state indices between 0xF and 0xFF.
|
|
Cxxx - for C-state indices greater than 0xFF.
|
|
*/
|
|
#define CSTS_SCOPE "CSTS"
|
|
#define CSTS_SCOPE_PREFIX SB_SCOPE_PREFIX CSTS_SCOPE "."
|
|
/// Size of the CSTS_SCOPE_PREFIX string.
|
|
#define CSTS_SCOPE_PREFIX_SIZE sizeof (CSTS_SCOPE_PREFIX)
|
|
|
|
/// HID for a processor device.
|
|
#define ACPI_HID_PROCESSOR_DEVICE "ACPI0007"
|
|
|
|
/// HID for a ETM/ETE device.
|
|
#define ACPI_HID_ET_DEVICE "ARMHC500"
|
|
|
|
/// HID for a processor container device.
|
|
#define ACPI_HID_PROCESSOR_CONTAINER_DEVICE "ACPI0010"
|
|
|
|
/** Node names of Cpus and Clusters are 'Cxxx', and 'Lxxx' for LPI states.
|
|
The 'xxx' is an index on 12 bits is given to node name,
|
|
thus the limitation in the number of nodes.
|
|
*/
|
|
#define MAX_NODE_COUNT (1 << 12)
|
|
|
|
/** A structure used to handle the Lpi structures referencing.
|
|
|
|
A CM_ARCH_COMMON_PROC_HIERARCHY_INFO structure references a CM_ARCH_COMMON_OBJ_REF.
|
|
This CM_ARCH_COMMON_OBJ_REF references CM_ARCH_COMMON_LPI_INFO structures.
|
|
|
|
Example:
|
|
(Cpu0) (Cpu1)
|
|
CM_ARCH_COMMON_PROC_HIERARCHY_INFO CM_ARCH_COMMON_PROC_HIERARCHY_INFO
|
|
| |
|
|
+----------------------------------------
|
|
|
|
|
v
|
|
(List of references to Lpi states)
|
|
CM_ARCH_COMMON_OBJ_REF
|
|
|
|
|
+----------------------------------------
|
|
| |
|
|
v v
|
|
(A first Lpi state) (A second Lpi state)
|
|
CM_ARCH_COMMON_LPI_INFO[0] CM_ARCH_COMMON_LPI_INFO[1]
|
|
|
|
Here, Cpu0 and Cpu1 have the same Lpi states. Both CM_ARCH_COMMON_PROC_HIERARCHY_INFO
|
|
structures reference the same CM_ARCH_COMMON_OBJ_REF. An entry is created in the
|
|
TokenTable such as:
|
|
0 <-> CM_ARCH_COMMON_OBJ_REF
|
|
|
|
This will lead to the creation of this pseudo-ASL code where Cpu0 and Cpu1
|
|
return the same object at \_SB.L000:
|
|
Scope (\_SB) {
|
|
Device (C000) {
|
|
[...]
|
|
Method (_LPI) {
|
|
Return (\_SB.L000)
|
|
}
|
|
} // C000
|
|
|
|
Device (C001) {
|
|
[...]
|
|
Method (_LPI) {
|
|
Return (\_SB.L000)
|
|
}
|
|
} // C001
|
|
|
|
// Lpi states
|
|
Name (L000, Package (0x05) {
|
|
[...]
|
|
}
|
|
}
|
|
*/
|
|
typedef struct TokenTable {
|
|
/// TokenTable, a table allowing to map:
|
|
/// Index <-> CM_OBJECT_TOKEN (to CM_ARCH_COMMON_LPI_INFO structures).
|
|
CM_OBJECT_TOKEN *Table;
|
|
|
|
/// Last used index of the TokenTable.
|
|
/// LastIndex is bound by ProcNodeCount.
|
|
UINT32 LastIndex;
|
|
} TOKEN_TABLE;
|
|
|
|
/** A structure holding the Cpu topology generator and additional private data.
|
|
*/
|
|
typedef struct AcpiCpuTopologyGenerator {
|
|
/// ACPI Table generator header
|
|
ACPI_TABLE_GENERATOR Header;
|
|
|
|
// Private fields are defined from here.
|
|
|
|
/// Private object used to handle token referencing.
|
|
TOKEN_TABLE TokenTable;
|
|
/// List of CM_ARCH_COMMON_PROC_HIERARCHY_INFO CM objects.
|
|
CM_ARCH_COMMON_PROC_HIERARCHY_INFO *ProcNodeList;
|
|
/// Count of CM_ARCH_COMMON_PROC_HIERARCHY_INFO CM objects.
|
|
UINT32 ProcNodeCount;
|
|
} ACPI_CPU_TOPOLOGY_GENERATOR;
|
|
|
|
#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
|
|
);
|
|
|
|
/** Create and add an _PSD 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 (_PSD, Package()
|
|
{
|
|
NumEntries, // Integer
|
|
Revision, // Integer
|
|
Domain, // Integer
|
|
CoordType, // Integer
|
|
NumProcessors, // Integer
|
|
})
|
|
}
|
|
|
|
@param [in] Generator The SSDT Cpu Topology generator.
|
|
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
|
|
Protocol Interface.
|
|
@param [in] PsdToken Token to identify the Psd information.
|
|
@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
|
|
CreateAmlPsdNode (
|
|
IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator,
|
|
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
|
|
IN CM_OBJECT_TOKEN PsdToken,
|
|
IN AML_OBJECT_NODE_HANDLE *Node
|
|
);
|
|
|
|
#endif // SSDT_CPU_TOPOLOGY_GENERATOR_H_
|