public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v3 0/3] DynamicTablesPkg: _CPC support
@ 2022-09-15 13:10 Jeff Brasen
  2022-09-15 13:10 ` [PATCH v3 1/3] DynamicTablesPkg: Add CM_ARM_CPC_INFO object Jeff Brasen
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Jeff Brasen @ 2022-09-15 13:10 UTC (permalink / raw)
  To: devel
  Cc: ardb+tianocore, Sami.Mujawar, Alexei.Fedorov, pierre.gondois,
	Jeff Brasen

Add generator for creating the _CPC object for CPU nodes.

If viewing this review by a pull request is helpful one exists here:
https://github.com/NVIDIA/edk2/pull/12

Change Log:
v1 - Initial Revision
v2 - Added revision to object, improved error handling, changed to ACPI 6.4 structures.
v3 - Minor review feedback

Jeff Brasen (3):
  DynamicTablesPkg: Add CM_ARM_CPC_INFO object
  DynamicTablesPkg: AML Code generation to add _CPC entries
  DynamicTablesPkg: SSDT CPU _CPC generator

 .../Include/ArmNameSpaceObjects.h             | 148 ++++-
 .../Include/Library/AmlLib/AmlLib.h           | 156 +++++
 .../SsdtCpuTopologyGenerator.c                | 223 ++++++-
 .../Common/AmlLib/CodeGen/AmlCodeGen.c        | 543 ++++++++++++++++++
 .../ConfigurationManagerObjectParser.c        |  80 +++
 5 files changed, 1127 insertions(+), 23 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 1/3] DynamicTablesPkg: Add CM_ARM_CPC_INFO object
  2022-09-15 13:10 [PATCH v3 0/3] DynamicTablesPkg: _CPC support Jeff Brasen
@ 2022-09-15 13:10 ` Jeff Brasen
  2022-09-15 15:14   ` Sami Mujawar
  2022-09-15 13:10 ` [PATCH v3 2/3] DynamicTablesPkg: AML Code generation to add _CPC entries Jeff Brasen
  2022-09-15 13:10 ` [PATCH v3 3/3] DynamicTablesPkg: SSDT CPU _CPC generator Jeff Brasen
  2 siblings, 1 reply; 7+ messages in thread
From: Jeff Brasen @ 2022-09-15 13:10 UTC (permalink / raw)
  To: devel
  Cc: ardb+tianocore, Sami.Mujawar, Alexei.Fedorov, pierre.gondois,
	Jeff Brasen

Introduce the CM_ARM_CPC_INFO CmObj in the ArmNameSpaceObjects.
This allows to describe CPC information, as described in ACPI 6.4,
s8.4.7.1 "_CPC (Continuous Performance Control)".

Signed-off-by: Jeff Brasen <jbrasen@nvidia.com>
---
 .../Include/ArmNameSpaceObjects.h             | 148 ++++++++++++++++--
 .../ConfigurationManagerObjectParser.c        |  80 ++++++++++
 2 files changed, 211 insertions(+), 17 deletions(-)

diff --git a/DynamicTablesPkg/Include/ArmNameSpaceObjects.h b/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
index 102e0f96be..d76cc08e14 100644
--- a/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
+++ b/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
@@ -63,6 +63,7 @@ typedef enum ArmObjectID {
   EArmObjPciInterruptMapInfo,          ///< 39 - Pci Interrupt Map Info
   EArmObjRmr,                          ///< 40 - Reserved Memory Range Node
   EArmObjMemoryRangeDescriptor,        ///< 41 - Memory Range Descriptor
+  EArmObjCpcInfo,                      ///< 42 - Continuous Performance Control Info
   EArmObjMax
 } EARM_OBJECT_ID;
 
@@ -97,99 +98,105 @@ typedef struct CmArmPowerManagementProfileInfo {
 */
 typedef struct CmArmGicCInfo {
   /// The GIC CPU Interface number.
-  UINT32    CPUInterfaceNumber;
+  UINT32             CPUInterfaceNumber;
 
   /** The ACPI Processor UID. This must match the
       _UID of the CPU Device object information described
       in the DSDT/SSDT for the CPU.
   */
-  UINT32    AcpiProcessorUid;
+  UINT32             AcpiProcessorUid;
 
   /** The flags field as described by the GICC structure
       in the ACPI Specification.
   */
-  UINT32    Flags;
+  UINT32             Flags;
 
   /** The parking protocol version field as described by
     the GICC structure in the ACPI Specification.
   */
-  UINT32    ParkingProtocolVersion;
+  UINT32             ParkingProtocolVersion;
 
   /** The Performance Interrupt field as described by
       the GICC structure in the ACPI Specification.
   */
-  UINT32    PerformanceInterruptGsiv;
+  UINT32             PerformanceInterruptGsiv;
 
   /** The CPU Parked address field as described by
       the GICC structure in the ACPI Specification.
   */
-  UINT64    ParkedAddress;
+  UINT64             ParkedAddress;
 
   /** The base address for the GIC CPU Interface
       as described by the GICC structure in the
       ACPI Specification.
   */
-  UINT64    PhysicalBaseAddress;
+  UINT64             PhysicalBaseAddress;
 
   /** The base address for GICV interface
       as described by the GICC structure in the
       ACPI Specification.
   */
-  UINT64    GICV;
+  UINT64             GICV;
 
   /** The base address for GICH interface
       as described by the GICC structure in the
       ACPI Specification.
   */
-  UINT64    GICH;
+  UINT64             GICH;
 
   /** The GICV maintenance interrupt
       as described by the GICC structure in the
       ACPI Specification.
   */
-  UINT32    VGICMaintenanceInterrupt;
+  UINT32             VGICMaintenanceInterrupt;
 
   /** The base address for GICR interface
       as described by the GICC structure in the
       ACPI Specification.
   */
-  UINT64    GICRBaseAddress;
+  UINT64             GICRBaseAddress;
 
   /** The MPIDR for the CPU
       as described by the GICC structure in the
       ACPI Specification.
   */
-  UINT64    MPIDR;
+  UINT64             MPIDR;
 
   /** The Processor Power Efficiency class
       as described by the GICC structure in the
       ACPI Specification.
   */
-  UINT8     ProcessorPowerEfficiencyClass;
+  UINT8              ProcessorPowerEfficiencyClass;
 
   /** Statistical Profiling Extension buffer overflow GSIV. Zero if
       unsupported by this processor. This field was introduced in
       ACPI 6.3 (MADT revision 5) and is therefore ignored when
       generating MADT revision 4 or lower.
   */
-  UINT16    SpeOverflowInterrupt;
+  UINT16             SpeOverflowInterrupt;
 
   /** The proximity domain to which the logical processor belongs.
       This field is used to populate the GICC affinity structure
       in the SRAT table.
   */
-  UINT32    ProximityDomain;
+  UINT32             ProximityDomain;
 
   /** The clock domain to which the logical processor belongs.
       This field is used to populate the GICC affinity structure
       in the SRAT table.
   */
-  UINT32    ClockDomain;
+  UINT32             ClockDomain;
 
   /** The GICC Affinity flags field as described by the GICC Affinity structure
       in the SRAT table.
   */
-  UINT32    AffinityFlags;
+  UINT32             AffinityFlags;
+
+  /** Optional field: Reference Token for the Cpc info of this processor.
+      Token identifying a CM_ARM_OBJ_REF structure, itself referencing
+      CM_ARM_CPC_INFO objects.
+  */
+  CM_OBJECT_TOKEN    CpcToken;
 } CM_ARM_GICC_INFO;
 
 /** A structure that describes the
@@ -1070,6 +1077,113 @@ typedef struct CmArmRmrDescriptor {
   UINT64    Length;
 } CM_ARM_MEMORY_RANGE_DESCRIPTOR;
 
+/** A structure that describes the Cpc information.
+
+  Continuous Performance Control is described in DSDT/SSDT and associated
+  to cpus/clusters in the cpu topology.
+
+  Unsupported Optional registers should be encoded with NULL resource
+  Register {(SystemMemory, 0, 0, 0, 0)}
+
+  For values that support Integer or Buffer, integer will be used
+  if buffer is NULL resource.
+  If resource is not NULL then Integer must be 0
+
+  Cf. ACPI 6.4, s8.4.7.1 _CPC (Continuous Performance Control)
+
+  ID: EArmObjCpcInfo
+*/
+typedef struct CmArmCpcInfo {
+  /// The revision number of the _CPC package format.
+  UINT32                                    Revision;
+
+  /// Indicates the highest level of performance the processor
+  /// is theoretically capable of achieving.
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    HighestPerformanceBuffer;
+  UINT32                                    HighestPerformanceInteger;
+
+  /// Indicates the highest sustained performance level of the processor.
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    NominalPerformanceBuffer;
+  UINT32                                    NominalPerformanceInteger;
+
+  /// Indicates the lowest performance level of the processor with non-linear power savings.
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    LowestNonlinearPerformanceBuffer;
+  UINT32                                    LowestNonlinearPerformanceInteger;
+
+  /// Indicates the lowest performance level of the processor..
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    LowestPerformanceBuffer;
+  UINT32                                    LowestPerformanceInteger;
+
+  /// Guaranteed Performance Register Buffer.
+  /// Optional
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    GuaranteedPerformanceRegister;
+
+  /// Desired Performance Register Buffer.
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    DesiredPerformanceRegister;
+
+  /// Minimum Performance Register Buffer.
+  /// Optional
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    MinimumPerformanceRegister;
+
+  /// Maximum Performance Register Buffer.
+  /// Optional
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    MaximumPerformanceRegister;
+
+  /// Performance Reduction Tolerance Register.
+  /// Optional
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    PerformanceReductionToleranceRegister;
+
+  /// Time Window Register.
+  /// Optional
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    TimeWindowRegister;
+
+  /// Counter Wraparound Time
+  /// Optional
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    CounterWraparoundTimeBuffer;
+  UINT32                                    CounterWraparoundTimeInteger;
+
+  /// Reference Performance Counter Register
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    ReferencePerformanceCounterRegister;
+
+  /// Delivered Performance Counter Register
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    DeliveredPerformanceCounterRegister;
+
+  /// Performance Limited Register
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    PerformanceLimitedRegister;
+
+  /// CPPC EnableRegister
+  /// Optional
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    CPPCEnableRegister;
+
+  /// Autonomous Selection Enable
+  /// Optional
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    AutonomousSelectionEnableBuffer;
+  UINT32                                    AutonomousSelectionEnableInteger;
+
+  /// AutonomousActivity-WindowRegister
+  /// Optional
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    AutonomousActivityWindowRegister;
+
+  /// EnergyPerformance-PreferenceRegister
+  /// Optional
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    EnergyPerformancePreferenceRegister;
+
+  /// Reference Performance
+  /// Optional
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    ReferencePerformanceBuffer;
+  UINT32                                    ReferencePerformanceInteger;
+
+  /// Lowest Frequency
+  /// Optional
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    LowestFrequencyBuffer;
+  UINT32                                    LowestFrequencyInteger;
+
+  /// Nominal Frequency
+  /// Optional
+  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    NominalFrequencyBuffer;
+  UINT32                                    NominalFrequencyInteger;
+} CM_ARM_CPC_INFO;
+
 #pragma pack()
 
 #endif // ARM_NAMESPACE_OBJECTS_H_
diff --git a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
index c1b21d24a4..c7e0d51397 100644
--- a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
+++ b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
@@ -423,6 +423,84 @@ STATIC CONST CM_OBJ_PARSER  CmPciInterruptMapInfoParser[] = {
     ARRAY_SIZE (CmArmGenericInterruptParser) },
 };
 
+/** A parser for EArmObjCpcInfo.
+*/
+STATIC CONST CM_OBJ_PARSER  CmArmCpcInfoParser[] = {
+  { "Revision",                              4,                                               "0x%llx", NULL },
+  { "HighestPerformanceBuffer",              sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "HighestPerformanceInteger",             4,                                               "0x%llx", NULL },
+  { "NominalPerformanceBuffer",              sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "NominalPerformanceInteger",             4,                                               "0x%llx", NULL },
+  { "LowestNonlinearPerformanceBuffer",      sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "LowestNonlinearPerformanceInteger",     4,                                               "0x%llx", NULL },
+  { "LowestPerformanceBuffer",               sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "LowestPerformanceInteger",              4,                                               "0x%llx", NULL },
+  { "GuaranteedPerformanceRegister",         sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "DesiredPerformanceRegister",            sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "MinimumPerformanceRegister",            sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "MaximumPerformanceRegister",            sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "PerformanceReductionToleranceRegister", sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "TimeWindowRegister",                    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "CounterWraparoundTimeBuffer",           sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "CounterWraparoundTimeInteger",          4,                                               "0x%llx", NULL },
+  { "ReferencePerformanceCounterRegister",   sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "DeliveredPerformanceCounterRegister",   sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "PerformanceLimitedRegister",            sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "CPPCEnableRegister",                    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "AutonomousSelectionEnableBuffer",       sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "AutonomousSelectionEnableInteger",      4,                                               "0x%llx", NULL },
+  { "AutonomousActivityWindowRegister",      sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "EnergyPerformancePreferenceRegister",   sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "ReferencePerformanceBuffer",            sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "ReferencePerformanceInteger",           4,                                               "0x%llx", NULL },
+  { "LowestFrequencyBuffer",                 sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "LowestFrequencyInteger",                4,                                               "0x%llx", NULL },
+  { "NominalFrequencyBuffer",                sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
+    NULL, NULL, AcpiGenericAddressParser,
+    ARRAY_SIZE (AcpiGenericAddressParser) },
+  { "NominalFrequencyInteger",               4,                                               "0x%llx", NULL },
+};
+
 /** A parser for Arm namespace objects.
 */
 STATIC CONST CM_OBJ_PARSER_ARRAY  ArmNamespaceObjectParser[] = {
@@ -501,6 +579,8 @@ STATIC CONST CM_OBJ_PARSER_ARRAY  ArmNamespaceObjectParser[] = {
     ARRAY_SIZE (CmArmPciAddressMapInfoParser) },
   { "EArmObjPciInterruptMapInfo",          CmPciInterruptMapInfoParser,
     ARRAY_SIZE (CmPciInterruptMapInfoParser) },
+  { "EArmObjCpcInfo",                      CmArmCpcInfoParser,
+    ARRAY_SIZE (CmArmCpcInfoParser) },
   { "EArmObjMax",                          NULL,                                  0                                },
 };
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 2/3] DynamicTablesPkg: AML Code generation to add _CPC entries
  2022-09-15 13:10 [PATCH v3 0/3] DynamicTablesPkg: _CPC support Jeff Brasen
  2022-09-15 13:10 ` [PATCH v3 1/3] DynamicTablesPkg: Add CM_ARM_CPC_INFO object Jeff Brasen
@ 2022-09-15 13:10 ` Jeff Brasen
  2022-09-15 15:16   ` Sami Mujawar
  2022-09-15 13:10 ` [PATCH v3 3/3] DynamicTablesPkg: SSDT CPU _CPC generator Jeff Brasen
  2 siblings, 1 reply; 7+ messages in thread
From: Jeff Brasen @ 2022-09-15 13:10 UTC (permalink / raw)
  To: devel
  Cc: ardb+tianocore, Sami.Mujawar, Alexei.Fedorov, pierre.gondois,
	Jeff Brasen

_CPC entries can describe CPU performance information.
The object is described in ACPI 6.4 s8.4.7.1.
"_CPC (Continuous Performance Control)".

Add AmlCreateCpcNode() helper function to add _CPC entries to an
existing CPU object.

Signed-off-by: Jeff Brasen <jbrasen@nvidia.com>
---
 .../Include/Library/AmlLib/AmlLib.h           | 156 +++++
 .../Common/AmlLib/CodeGen/AmlCodeGen.c        | 543 ++++++++++++++++++
 2 files changed, 699 insertions(+)

diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
index 39968660f2..3fafa6b0e8 100644
--- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
+++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
@@ -1336,6 +1336,162 @@ AmlAddNameIntegerPackage (
   IN AML_OBJECT_NODE_HANDLE  PackageNode
   );
 
+/** Create a _CPC node.
+
+  Creates and optionally adds the following node
+   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)
+  })
+
+  If resource buffer is NULL then integer will be used.
+
+  Cf. ACPI 6.4, s8.4.7.1 _CPC (Continuous Performance Control)
+
+  @ingroup CodeGenApis
+
+  @param [in]  HighestPerformanceBuffer               If provided, buffer that indicates the highest level
+                                                      of performance the processor.
+  @param [in]  HighestPerformanceInteger              Indicates the highest level of performance the processor,
+                                                      used if buffer is NULL.
+  @param [in]  NominalPerformanceBuffer               If provided buffer that indicates the highest sustained
+                                                      performance level of the processor.
+  @param [in]  NominalPerformanceInteger              Indicates the highest sustained performance level
+                                                      of the processor, used if buffer is NULL.
+  @param [in]  LowestNonlinearPerformanceBuffer       If provided, buffer that indicates the lowest performance level
+                                                      of the processor with non-linear power savings.
+  @param [in]  LowestNonlinearPerformanceInteger      Indicates the lowest performance level of the processor with
+                                                      non-linear power savings, used if buffer is NULL.
+  @param [in]  LowestPerformanceBuffer                If provided, buffer that indicates the
+                                                      lowest performance level of the processor.
+  @param [in]  LowestPerformanceInteger               Indicates the lowest performance level of the processor,
+                                                      used if buffer is NULL.
+  @param [in]  GuaranteedPerformanceRegister          If provided, Guaranteed Performance Register Buffer.
+  @param [in]  DesiredPerformanceRegister             If provided, Desired Performance Register Buffer.
+  @param [in]  MinimumPerformanceRegister             If provided, Minimum Performance Register Buffer.
+  @param [in]  MaximumPerformanceRegister             If provided, Maximum Performance Register Buffer.
+  @param [in]  PerformanceReductionToleranceRegister  If provided, Performance Reduction Tolerance Register.
+  @param [in]  TimeWindowRegister                     If provided, Time Window Register.
+  @param [in]  CounterWraparoundTimeBuffer            If provided, Counter Wraparound Time buffer.
+  @param [in]  CounterWraparoundTimeInteger           Counter Wraparound Time, used if buffer is NULL.
+  @param [in]  ReferencePerformanceCounterRegister    Reference Performance Counter Register.
+  @param [in]  DeliveredPerformanceCounterRegister    Delivered Performance Counter Register.
+  @param [in]  PerformanceLimitedRegister             Performance Limited Register.
+  @param [in]  CPPCEnableRegister                     If provided, CPPC EnableRegister.
+  @param [in]  AutonomousSelectionEnableBuffer        If provided, Autonomous Selection Enable buffer.
+  @param [in]  AutonomousSelectionEnableInteger       Autonomous Selection Enable, used if buffer is NULL.
+  @param [in]  AutonomousActivityWindowRegister       If provided, AutonomousActivity-WindowRegister.
+  @param [in]  EnergyPerformancePreferenceRegister    If provided, EnergyPerformance-PreferenceRegister.
+  @param [in]  ReferencePerformanceBuffer             If provided, Reference Performance buffer.
+  @param [in]  ReferencePerformanceInteger            Reference Performance, used if buffer is NULL.
+  @param [in]  LowestFrequencyBuffer                  If provided, Lowest Frequency buffer.
+  @param [in]  LowestFrequencyInteger                 Lowest Frequency, used if buffer is NULL.
+  @param [in]  NominalFrequencyBuffer                 If provided, NominalFrequencyBuffer buffer.
+  @param [in]  NominalFrequencyInteger                NominalFrequencyBuffer, used if buffer is NULL.
+  @param [in]  ParentNode                             If provided, set ParentNode as the parent
+                                                      of the node created.
+  @param [out] NewCpcNode                             If success and provided, contains the created node.
+
+  @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
+AmlCreateCpcNode (
+  /// The revision number of the _CPC package format.
+  IN  UINT32  Revision,
+  /// Indicates the highest level of performance the processor
+  /// is theoretically capable of achieving.
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *HighestPerformanceBuffer OPTIONAL,
+  IN  UINT32                                  HighestPerformanceInteger,
+  /// Indicates the highest sustained performance level of the processor.
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE   *NominalPerformanceBuffer OPTIONAL,
+  IN UINT32                                   NominalPerformanceInteger,
+  /// Indicates the lowest performance level of the processor with non-linear power savings.
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *LowestNonlinearPerformanceBuffer OPTIONAL,
+  IN UINT32                                   LowestNonlinearPerformanceInteger,
+  /// Indicates the lowest performance level of the processor..
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *LowestPerformanceBuffer OPTIONAL,
+  IN  UINT32                                  LowestPerformanceInteger,
+  /// Guaranteed Performance Register Buffer.
+  /// Optional
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *GuaranteedPerformanceRegister OPTIONAL,
+  /// Desired Performance Register Buffer.
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *DesiredPerformanceRegister,
+  /// Minimum Performance Register Buffer.
+  /// Optional
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *MinimumPerformanceRegister OPTIONAL,
+  /// Maximum Performance Register Buffer.
+  /// Optional
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *MaximumPerformanceRegister OPTIONAL,
+  /// Performance Reduction Tolerance Register.
+  /// Optional
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *PerformanceReductionToleranceRegister OPTIONAL,
+  /// Time Window Register.
+  /// Optional
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *TimeWindowRegister OPTIONAL,
+  /// Counter Wraparound Time
+  /// Optional
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *CounterWraparoundTimeBuffer OPTIONAL,
+  IN  UINT32                                  CounterWraparoundTimeInteger,
+  /// Reference Performance Counter Register
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *ReferencePerformanceCounterRegister,
+  /// Delivered Performance Counter Register
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *DeliveredPerformanceCounterRegister,
+  /// Performance Limited Register
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *PerformanceLimitedRegister,
+  /// CPPC EnableRegister
+  /// Optional
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *CPPCEnableRegister OPTIONAL,
+  /// Autonomous Selection Enable
+  /// Optional
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *AutonomousSelectionEnableBuffer OPTIONAL,
+  IN  UINT32                                  AutonomousSelectionEnableInteger,
+  /// AutonomousActivity-WindowRegister
+  /// Optional
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *AutonomousActivityWindowRegister OPTIONAL,
+  /// EnergyPerformance-PreferenceRegister
+  /// Optional
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *EnergyPerformancePreferenceRegister OPTIONAL,
+  /// Reference Performance
+  /// Optional
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *ReferencePerformanceBuffer OPTIONAL,
+  IN  UINT32                                  ReferencePerformanceInteger,
+  /// Lowest Frequency
+  /// Optional
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *LowestFrequencyBuffer OPTIONAL,
+  IN  UINT32                                  LowestFrequencyInteger,
+  /// Nominal Frequency
+  /// Optional
+  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *NominalFrequencyBuffer OPTIONAL,
+  IN  UINT32                                  NominalFrequencyInteger,
+  IN  AML_NODE_HANDLE                         ParentNode   OPTIONAL,
+  OUT AML_OBJECT_NODE_HANDLE                  *NewCpcNode   OPTIONAL
+  );
+
 // DEPRECATED APIS
 #ifndef DISABLE_NEW_DEPRECATED_INTERFACES
 
diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
index 5fb39d077b..42f0d0002c 100644
--- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
+++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
@@ -2850,3 +2850,546 @@ error_handler:
 
   return Status;
 }
+
+/** Adds a register to the package
+
+  @ingroup CodeGenApis
+
+  @param [in]  Register     If provided, register that will be added to package.
+                            otherwise NULL register will be added
+  @param [in]  PackageNode  Package to add value to
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlAddRegisterToPackage (
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *Register OPTIONAL,
+  IN AML_OBJECT_NODE_HANDLE                  PackageNode
+  )
+{
+  EFI_STATUS              Status;
+  AML_DATA_NODE_HANDLE    RdNode;
+  AML_OBJECT_NODE_HANDLE  ResourceTemplateNode;
+
+  RdNode = NULL;
+
+  Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  if (Register != NULL) {
+    Status = AmlCodeGenRdRegister (
+               Register->AddressSpaceId,
+               Register->RegisterBitWidth,
+               Register->RegisterBitOffset,
+               Register->Address,
+               Register->AccessSize,
+               NULL,
+               &RdNode
+               );
+  } else {
+    Status = AmlCodeGenRdRegister (
+               EFI_ACPI_6_4_SYSTEM_MEMORY,
+               0,
+               0,
+               0,
+               0,
+               NULL,
+               &RdNode
+               );
+  }
+
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAppendRdNode (ResourceTemplateNode, RdNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  RdNode = NULL;
+
+  Status = AmlVarListAddTail (
+             (AML_NODE_HANDLE)PackageNode,
+             (AML_NODE_HANDLE)ResourceTemplateNode
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  return Status;
+
+error_handler:
+  if (RdNode != NULL) {
+    AmlDeleteTree ((AML_NODE_HANDLE)RdNode);
+  }
+
+  if (ResourceTemplateNode != NULL) {
+    AmlDeleteTree ((AML_NODE_HANDLE)ResourceTemplateNode);
+  }
+
+  return Status;
+}
+
+/** Adds an integer or register to the package
+
+  @ingroup CodeGenApis
+
+  @param [in]  Register     If provided, register that will be added to package
+  @param [in]  Integer      If Register is NULL, integer that will be added to the package
+  @param [in]  PackageNode  Package to add value to
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlAddRegisterOrIntegerToPackage (
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *Register OPTIONAL,
+  IN UINT32                                  Integer,
+  IN AML_OBJECT_NODE_HANDLE                  PackageNode
+  )
+{
+  EFI_STATUS              Status;
+  AML_OBJECT_NODE_HANDLE  IntegerNode;
+
+  IntegerNode = NULL;
+
+  if (Register != NULL) {
+    Status = AmlAddRegisterToPackage (Register, PackageNode);
+  } else {
+    Status = AmlCodeGenInteger (Integer, &IntegerNode);
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      return Status;
+    }
+
+    Status = AmlVarListAddTail (
+               (AML_NODE_HANDLE)PackageNode,
+               (AML_NODE_HANDLE)IntegerNode
+               );
+  }
+
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    if (IntegerNode != NULL) {
+      AmlDeleteTree ((AML_NODE_HANDLE)IntegerNode);
+    }
+  }
+
+  return Status;
+}
+
+/** Create a _CPC node.
+
+  Creates and optionally adds the following node
+   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)
+  })
+
+  If resource buffer is NULL then integer will be used.
+
+  Cf. ACPI 6.4, s8.4.7.1 _CPC (Continuous Performance Control)
+
+  @ingroup CodeGenApis
+
+  @param [in]  HighestPerformanceBuffer               If provided, buffer that indicates the highest level
+                                                      of performance the processor.
+  @param [in]  HighestPerformanceInteger              Indicates the highest level of performance the processor,
+                                                      used if buffer is NULL.
+  @param [in]  NominalPerformanceBuffer               If provided buffer that indicates the highest sustained
+                                                      performance level of the processor.
+  @param [in]  NominalPerformanceInteger              Indicates the highest sustained performance level
+                                                      of the processor, used if buffer is NULL.
+  @param [in]  LowestNonlinearPerformanceBuffer       If provided, buffer that indicates the lowest performance level
+                                                      of the processor with non-linear power savings.
+  @param [in]  LowestNonlinearPerformanceInteger      Indicates the lowest performance level of the processor with
+                                                      non-linear power savings, used if buffer is NULL.
+  @param [in]  LowestPerformanceBuffer                If provided, buffer that indicates the
+                                                      lowest performance level of the processor.
+  @param [in]  LowestPerformanceInteger               Indicates the lowest performance level of the processor,
+                                                      used if buffer is NULL.
+  @param [in]  GuaranteedPerformanceRegister          If provided, Guaranteed Performance Register Buffer.
+  @param [in]  DesiredPerformanceRegister             If provided, Desired Performance Register Buffer.
+  @param [in]  MinimumPerformanceRegister             If provided, Minimum Performance Register Buffer.
+  @param [in]  MaximumPerformanceRegister             If provided, Maximum Performance Register Buffer.
+  @param [in]  PerformanceReductionToleranceRegister  If provided, Performance Reduction Tolerance Register.
+  @param [in]  TimeWindowRegister                     If provided, Time Window Register.
+  @param [in]  CounterWraparoundTimeBuffer            If provided, Counter Wraparound Time buffer.
+  @param [in]  CounterWraparoundTimeInteger           Counter Wraparound Time, used if buffer is NULL.
+  @param [in]  ReferencePerformanceCounterRegister    Reference Performance Counter Register.
+  @param [in]  DeliveredPerformanceCounterRegister    Delivered Performance Counter Register.
+  @param [in]  PerformanceLimitedRegister             Performance Limited Register.
+  @param [in]  CPPCEnableRegister                     If provided, CPPC EnableRegister.
+  @param [in]  AutonomousSelectionEnableBuffer        If provided, Autonomous Selection Enable buffer.
+  @param [in]  AutonomousSelectionEnableInteger       Autonomous Selection Enable, used if buffer is NULL.
+  @param [in]  AutonomousActivityWindowRegister       If provided, AutonomousActivity-WindowRegister.
+  @param [in]  EnergyPerformancePreferenceRegister    If provided, EnergyPerformance-PreferenceRegister.
+  @param [in]  ReferencePerformanceBuffer             If provided, Reference Performance buffer.
+  @param [in]  ReferencePerformanceInteger            Reference Performance, used if buffer is NULL.
+  @param [in]  LowestFrequencyBuffer                  If provided, Lowest Frequency buffer.
+  @param [in]  LowestFrequencyInteger                 Lowest Frequency, used if buffer is NULL.
+  @param [in]  NominalFrequencyBuffer                 If provided, NominalFrequencyBuffer buffer.
+  @param [in]  NominalFrequencyInteger                NominalFrequencyBuffer, used if buffer is NULL.
+  @param [in]  ParentNode                             If provided, set ParentNode as the parent
+                                                      of the node created.
+  @param [out] NewCpcNode                             If success and provided, contains the created node.
+
+  @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
+AmlCreateCpcNode (
+  /// The revision number of the _CPC package format.
+  IN  UINT32  Revision,
+  /// Indicates the highest level of performance the processor
+  /// is theoretically capable of achieving.
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *HighestPerformanceBuffer OPTIONAL,
+  IN UINT32                                  HighestPerformanceInteger,
+  /// Indicates the highest sustained performance level of the processor.
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *NominalPerformanceBuffer OPTIONAL,
+  IN UINT32                                  NominalPerformanceInteger,
+  /// Indicates the lowest performance level of the processor with non-linear power savings.
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *LowestNonlinearPerformanceBuffer OPTIONAL,
+  IN UINT32                                  LowestNonlinearPerformanceInteger,
+  /// Indicates the lowest performance level of the processor..
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *LowestPerformanceBuffer OPTIONAL,
+  IN UINT32                                  LowestPerformanceInteger,
+  /// Guaranteed Performance Register Buffer.
+  /// Optional
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *GuaranteedPerformanceRegister OPTIONAL,
+  /// Desired Performance Register Buffer.
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *DesiredPerformanceRegister,
+  /// Minimum Performance Register Buffer.
+  /// Optional
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *MinimumPerformanceRegister OPTIONAL,
+  /// Maximum Performance Register Buffer.
+  /// Optional
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *MaximumPerformanceRegister OPTIONAL,
+  /// Performance Reduction Tolerance Register.
+  /// Optional
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *PerformanceReductionToleranceRegister OPTIONAL,
+  /// Time Window Register.
+  /// Optional
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *TimeWindowRegister OPTIONAL,
+  /// Counter Wraparound Time
+  /// Optional
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *CounterWraparoundTimeBuffer OPTIONAL,
+  IN UINT32                                  CounterWraparoundTimeInteger,
+  /// Reference Performance Counter Register
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *ReferencePerformanceCounterRegister,
+  /// Delivered Performance Counter Register
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *DeliveredPerformanceCounterRegister,
+  /// Performance Limited Register
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *PerformanceLimitedRegister,
+  /// CPPC EnableRegister
+  /// Optional
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *CPPCEnableRegister OPTIONAL,
+  /// Autonomous Selection Enable
+  /// Optional
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *AutonomousSelectionEnableBuffer OPTIONAL,
+  IN UINT32                                  AutonomousSelectionEnableInteger,
+  /// AutonomousActivity-WindowRegister
+  /// Optional
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *AutonomousActivityWindowRegister OPTIONAL,
+  /// EnergyPerformance-PreferenceRegister
+  /// Optional
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *EnergyPerformancePreferenceRegister OPTIONAL,
+  /// Reference Performance
+  /// Optional
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *ReferencePerformanceBuffer OPTIONAL,
+  IN UINT32                                  ReferencePerformanceInteger,
+  /// Lowest Frequency
+  /// Optional
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *LowestFrequencyBuffer OPTIONAL,
+  IN UINT32                                  LowestFrequencyInteger,
+  /// Nominal Frequency
+  /// Optional
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *NominalFrequencyBuffer OPTIONAL,
+  IN UINT32                                  NominalFrequencyInteger,
+  IN AML_NODE_HANDLE                         ParentNode OPTIONAL,
+  OUT AML_OBJECT_NODE_HANDLE                 *NewCpcNode OPTIONAL
+  )
+{
+  EFI_STATUS              Status;
+  AML_OBJECT_NODE_HANDLE  CpcNode;
+  AML_OBJECT_NODE_HANDLE  CpcPackage;
+  UINT32                  NumberOfEntries;
+
+  // Revision 3 per ACPI 6.4 specification
+  if (Revision == 3) {
+    // NumEntries 23 per ACPI 6.4 specification
+    NumberOfEntries = 23;
+  } else {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (((HighestPerformanceBuffer == NULL) && (HighestPerformanceInteger == 0)) ||
+      ((NominalPerformanceBuffer == NULL) && (NominalPerformanceInteger == 0)) ||
+      ((LowestNonlinearPerformanceBuffer == NULL) && (LowestNonlinearPerformanceInteger == 0)) ||
+      ((LowestPerformanceBuffer == NULL) && (LowestPerformanceInteger == 0)) ||
+      (DesiredPerformanceRegister == NULL)    ||
+      (ReferencePerformanceCounterRegister == NULL)    ||
+      (DeliveredPerformanceCounterRegister == NULL)    ||
+      (PerformanceLimitedRegister == NULL)             ||
+      ((ParentNode == NULL) && (NewCpcNode == NULL)))
+  {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CpcPackage = NULL;
+
+  Status = AmlCodeGenNamePackage ("_CPC", NULL, &CpcNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  // Get the Package object node of the _CPC node,
+  // which is the 2nd fixed argument (i.e. index 1).
+  CpcPackage = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (
+                                         CpcNode,
+                                         EAmlParseIndexTerm1
+                                         );
+  if ((CpcPackage == NULL)                                              ||
+      (AmlGetNodeType ((AML_NODE_HANDLE)CpcPackage) != EAmlNodeObject)  ||
+      (!AmlNodeHasOpCode (CpcPackage, AML_PACKAGE_OP, 0)))
+  {
+    ASSERT (0);
+    Status = EFI_INVALID_PARAMETER;
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterOrIntegerToPackage (
+             NULL,
+             NumberOfEntries,
+             CpcPackage
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterOrIntegerToPackage (
+             NULL,
+             Revision,
+             CpcPackage
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterOrIntegerToPackage (
+             HighestPerformanceBuffer,
+             HighestPerformanceInteger,
+             CpcPackage
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterOrIntegerToPackage (
+             NominalPerformanceBuffer,
+             NominalPerformanceInteger,
+             CpcPackage
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterOrIntegerToPackage (
+             LowestNonlinearPerformanceBuffer,
+             LowestNonlinearPerformanceInteger,
+             CpcPackage
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterOrIntegerToPackage (
+             LowestPerformanceBuffer,
+             LowestPerformanceInteger,
+             CpcPackage
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterToPackage (GuaranteedPerformanceRegister, CpcPackage);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterToPackage (DesiredPerformanceRegister, CpcPackage);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterToPackage (MinimumPerformanceRegister, CpcPackage);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterToPackage (MaximumPerformanceRegister, CpcPackage);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterToPackage (PerformanceReductionToleranceRegister, CpcPackage);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterToPackage (TimeWindowRegister, CpcPackage);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterOrIntegerToPackage (
+             CounterWraparoundTimeBuffer,
+             CounterWraparoundTimeInteger,
+             CpcPackage
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterToPackage (ReferencePerformanceCounterRegister, CpcPackage);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterToPackage (DeliveredPerformanceCounterRegister, CpcPackage);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterToPackage (PerformanceLimitedRegister, CpcPackage);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterToPackage (CPPCEnableRegister, CpcPackage);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterOrIntegerToPackage (
+             AutonomousSelectionEnableBuffer,
+             AutonomousSelectionEnableInteger,
+             CpcPackage
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterToPackage (AutonomousActivityWindowRegister, CpcPackage);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterToPackage (EnergyPerformancePreferenceRegister, CpcPackage);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterOrIntegerToPackage (
+             ReferencePerformanceBuffer,
+             ReferencePerformanceInteger,
+             CpcPackage
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterOrIntegerToPackage (
+             LowestFrequencyBuffer,
+             LowestFrequencyInteger,
+             CpcPackage
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = AmlAddRegisterOrIntegerToPackage (
+             NominalFrequencyBuffer,
+             NominalFrequencyInteger,
+             CpcPackage
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = LinkNode (CpcNode, ParentNode, NewCpcNode);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  return Status;
+
+error_handler:
+  AmlDeleteTree ((AML_NODE_HANDLE)CpcNode);
+  return Status;
+}
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 3/3] DynamicTablesPkg: SSDT CPU _CPC generator
  2022-09-15 13:10 [PATCH v3 0/3] DynamicTablesPkg: _CPC support Jeff Brasen
  2022-09-15 13:10 ` [PATCH v3 1/3] DynamicTablesPkg: Add CM_ARM_CPC_INFO object Jeff Brasen
  2022-09-15 13:10 ` [PATCH v3 2/3] DynamicTablesPkg: AML Code generation to add _CPC entries Jeff Brasen
@ 2022-09-15 13:10 ` Jeff Brasen
  2022-09-15 15:16   ` Sami Mujawar
  2 siblings, 1 reply; 7+ messages in thread
From: Jeff Brasen @ 2022-09-15 13:10 UTC (permalink / raw)
  To: devel
  Cc: ardb+tianocore, Sami.Mujawar, Alexei.Fedorov, pierre.gondois,
	Jeff Brasen

Add code to use a token attached to GICC to generate _CPC object on cpus.

Signed-off-by: Jeff Brasen <jbrasen@nvidia.com>
---
 .../SsdtCpuTopologyGenerator.c                | 223 +++++++++++++++++-
 1 file changed, 217 insertions(+), 6 deletions(-)

diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c
index 8561f48e1f..5d41d57064 100644
--- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c
@@ -76,6 +76,16 @@ GET_OBJECT_LIST (
   CM_ARM_LPI_INFO
   );
 
+/**
+  This macro expands to a function that retrieves the CPC
+  information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjCpcInfo,
+  CM_ARM_CPC_INFO
+  );
+
 /** Initialize the TokenTable.
 
   One entry should be allocated for each CM_ARM_PROC_HIERARCHY_INFO
@@ -229,6 +239,183 @@ WriteAslName (
   return EFI_SUCCESS;
 }
 
+/** Utility function to check if generic address points to NULL
+
+  @param [in]  Address  Pointer to the Generic address
+
+  @retval TRUE          Address is system memory with an Address of 0.
+  @retval FALSE         Address does not point to NULL.
+**/
+STATIC
+BOOLEAN
+EFIAPI
+IsNullGenericAddress (
+  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *Address
+  )
+{
+  if ((Address == NULL) ||
+      ((Address->AddressSpaceId == EFI_ACPI_6_4_SYSTEM_MEMORY) &&
+       (Address->Address == 0x0)))
+  {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/** 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]  ProcHierarchyNodeInfo  CM_ARM_PROC_HIERARCHY_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.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CreateAmlCpcNode (
+  IN  ACPI_CPU_TOPOLOGY_GENERATOR                         *Generator,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol,
+  IN    CM_ARM_GICC_INFO                                  *GicCInfo,
+  IN  AML_OBJECT_NODE_HANDLE                              *Node
+  )
+{
+  EFI_STATUS       Status;
+  CM_ARM_CPC_INFO  *CpcInfo;
+
+  Status = GetEArmObjCpcInfo (
+             CfgMgrProtocol,
+             GicCInfo->CpcToken,
+             &CpcInfo,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  Status = AmlCreateCpcNode (
+             CpcInfo->Revision,
+             IsNullGenericAddress (&CpcInfo->HighestPerformanceBuffer) ?
+             NULL :
+             &CpcInfo->HighestPerformanceBuffer,
+             CpcInfo->HighestPerformanceInteger,
+             IsNullGenericAddress (&CpcInfo->NominalPerformanceBuffer) ?
+             NULL :
+             &CpcInfo->NominalPerformanceBuffer,
+             CpcInfo->NominalPerformanceInteger,
+             IsNullGenericAddress (&CpcInfo->LowestNonlinearPerformanceBuffer) ?
+             NULL :
+             &CpcInfo->LowestNonlinearPerformanceBuffer,
+             CpcInfo->LowestNonlinearPerformanceInteger,
+             IsNullGenericAddress (&CpcInfo->LowestPerformanceBuffer) ?
+             NULL :
+             &CpcInfo->LowestPerformanceBuffer,
+             CpcInfo->LowestPerformanceInteger,
+             IsNullGenericAddress (&CpcInfo->GuaranteedPerformanceRegister) ?
+             NULL :
+             &CpcInfo->GuaranteedPerformanceRegister,
+             IsNullGenericAddress (&CpcInfo->DesiredPerformanceRegister) ?
+             NULL :
+             &CpcInfo->DesiredPerformanceRegister,
+             IsNullGenericAddress (&CpcInfo->MinimumPerformanceRegister) ?
+             NULL :
+             &CpcInfo->MinimumPerformanceRegister,
+             IsNullGenericAddress (&CpcInfo->MaximumPerformanceRegister) ?
+             NULL :
+             &CpcInfo->MaximumPerformanceRegister,
+             IsNullGenericAddress (&CpcInfo->PerformanceReductionToleranceRegister) ?
+             NULL :
+             &CpcInfo->PerformanceReductionToleranceRegister,
+             IsNullGenericAddress (&CpcInfo->TimeWindowRegister) ?
+             NULL :
+             &CpcInfo->TimeWindowRegister,
+             IsNullGenericAddress (&CpcInfo->CounterWraparoundTimeBuffer) ?
+             NULL :
+             &CpcInfo->CounterWraparoundTimeBuffer,
+             CpcInfo->CounterWraparoundTimeInteger,
+             &CpcInfo->ReferencePerformanceCounterRegister,
+             &CpcInfo->DeliveredPerformanceCounterRegister,
+             &CpcInfo->PerformanceLimitedRegister,
+             IsNullGenericAddress (&CpcInfo->CPPCEnableRegister) ?
+             NULL :
+             &CpcInfo->CPPCEnableRegister,
+             IsNullGenericAddress (&CpcInfo->AutonomousSelectionEnableBuffer) ?
+             NULL :
+             &CpcInfo->AutonomousSelectionEnableBuffer,
+             CpcInfo->AutonomousSelectionEnableInteger,
+             IsNullGenericAddress (&CpcInfo->AutonomousActivityWindowRegister) ?
+             NULL :
+             &CpcInfo->AutonomousActivityWindowRegister,
+             IsNullGenericAddress (&CpcInfo->EnergyPerformancePreferenceRegister) ?
+             NULL :
+             &CpcInfo->EnergyPerformancePreferenceRegister,
+             IsNullGenericAddress (&CpcInfo->ReferencePerformanceBuffer) ?
+             NULL :
+             &CpcInfo->ReferencePerformanceBuffer,
+             CpcInfo->ReferencePerformanceInteger,
+             IsNullGenericAddress (&CpcInfo->LowestFrequencyBuffer) ?
+             NULL :
+             &CpcInfo->LowestFrequencyBuffer,
+             CpcInfo->LowestFrequencyInteger,
+             IsNullGenericAddress (&CpcInfo->NominalFrequencyBuffer) ?
+             NULL :
+             &CpcInfo->NominalFrequencyBuffer,
+             CpcInfo->NominalFrequencyInteger,
+             Node,
+             NULL
+             );
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
+
 /** Create and add an _LPI method to Cpu/Cluster Node.
 
   For instance, transform an AML node from:
@@ -581,7 +768,20 @@ CreateAmlCpuFromProcHierarchy (
   // CM_ARM_PROC_HIERARCHY_INFO, create an _LPI method returning them.
   if (ProcHierarchyNodeInfo->LpiToken != CM_NULL_TOKEN) {
     Status = CreateAmlLpiMethod (Generator, ProcHierarchyNodeInfo, CpuNode);
-    ASSERT_EFI_ERROR (Status);
+    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->CpcToken != CM_NULL_TOKEN) {
+    Status = CreateAmlCpcNode (Generator, CfgMgrProtocol, GicCInfo, CpuNode);
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      return Status;
+    }
   }
 
   return Status;
@@ -934,10 +1134,11 @@ CreateTopologyFromGicC (
   IN        AML_OBJECT_NODE_HANDLE                        ScopeNode
   )
 {
-  EFI_STATUS        Status;
-  CM_ARM_GICC_INFO  *GicCInfo;
-  UINT32            GicCInfoCount;
-  UINT32            Index;
+  EFI_STATUS              Status;
+  CM_ARM_GICC_INFO        *GicCInfo;
+  UINT32                  GicCInfoCount;
+  UINT32                  Index;
+  AML_OBJECT_NODE_HANDLE  CpuNode;
 
   ASSERT (Generator != NULL);
   ASSERT (CfgMgrProtocol != NULL);
@@ -961,12 +1162,22 @@ CreateTopologyFromGicC (
                ScopeNode,
                &GicCInfo[Index],
                Index,
-               NULL
+               &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->CpcToken != CM_NULL_TOKEN) {
+      Status = CreateAmlCpcNode (Generator, CfgMgrProtocol, &GicCInfo[Index], CpuNode);
+      if (EFI_ERROR (Status)) {
+        ASSERT_EFI_ERROR (Status);
+        break;
+      }
+    }
   } // for
 
   return Status;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 1/3] DynamicTablesPkg: Add CM_ARM_CPC_INFO object
  2022-09-15 13:10 ` [PATCH v3 1/3] DynamicTablesPkg: Add CM_ARM_CPC_INFO object Jeff Brasen
@ 2022-09-15 15:14   ` Sami Mujawar
  0 siblings, 0 replies; 7+ messages in thread
From: Sami Mujawar @ 2022-09-15 15:14 UTC (permalink / raw)
  To: Jeff Brasen, devel
  Cc: ardb+tianocore, Alexei.Fedorov, pierre.gondois, nd@arm.com

[-- Attachment #1: Type: text/plain, Size: 18787 bytes --]

Hi Jeff,

Please find my feedback inline marked [SAMI].

Regards,

Sami Mujawar

On 15/09/2022 02:10 pm, Jeff Brasen wrote:
> Introduce the CM_ARM_CPC_INFO CmObj in the ArmNameSpaceObjects.
>
> This allows to describe CPC information, as described in ACPI 6.4,
>
> s8.4.7.1 "_CPC (Continuous Performance Control)".
>
>
>
> Signed-off-by: Jeff Brasen<jbrasen@nvidia.com>
>
> ---
>
>   .../Include/ArmNameSpaceObjects.h             | 148 ++++++++++++++++--
>
>   .../ConfigurationManagerObjectParser.c        |  80 ++++++++++
>
>   2 files changed, 211 insertions(+), 17 deletions(-)
>
>
>
> diff --git a/DynamicTablesPkg/Include/ArmNameSpaceObjects.h b/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
>
> index 102e0f96be..d76cc08e14 100644
>
> --- a/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
>
> +++ b/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
>
> @@ -63,6 +63,7 @@ typedef enum ArmObjectID {
>
>     EArmObjPciInterruptMapInfo,          ///< 39 - Pci Interrupt Map Info
>
>     EArmObjRmr,                          ///< 40 - Reserved Memory Range Node
>
>     EArmObjMemoryRangeDescriptor,        ///< 41 - Memory Range Descriptor
>
> +  EArmObjCpcInfo,                      ///< 42 - Continuous Performance Control Info
>
>     EArmObjMax
>
>   } EARM_OBJECT_ID;
>
>   
>
> @@ -97,99 +98,105 @@ typedef struct CmArmPowerManagementProfileInfo {
>
>   */
>
>   typedef struct CmArmGicCInfo {
>
>     /// The GIC CPU Interface number.
>
> -  UINT32    CPUInterfaceNumber;
>
> +  UINT32             CPUInterfaceNumber;
>
>   
>
>     /** The ACPI Processor UID. This must match the
>
>         _UID of the CPU Device object information described
>
>         in the DSDT/SSDT for the CPU.
>
>     */
>
> -  UINT32    AcpiProcessorUid;
>
> +  UINT32             AcpiProcessorUid;
>
>   
>
>     /** The flags field as described by the GICC structure
>
>         in the ACPI Specification.
>
>     */
>
> -  UINT32    Flags;
>
> +  UINT32             Flags;
>
>   
>
>     /** The parking protocol version field as described by
>
>       the GICC structure in the ACPI Specification.
>
>     */
>
> -  UINT32    ParkingProtocolVersion;
>
> +  UINT32             ParkingProtocolVersion;
>
>   
>
>     /** The Performance Interrupt field as described by
>
>         the GICC structure in the ACPI Specification.
>
>     */
>
> -  UINT32    PerformanceInterruptGsiv;
>
> +  UINT32             PerformanceInterruptGsiv;
>
>   
>
>     /** The CPU Parked address field as described by
>
>         the GICC structure in the ACPI Specification.
>
>     */
>
> -  UINT64    ParkedAddress;
>
> +  UINT64             ParkedAddress;
>
>   
>
>     /** The base address for the GIC CPU Interface
>
>         as described by the GICC structure in the
>
>         ACPI Specification.
>
>     */
>
> -  UINT64    PhysicalBaseAddress;
>
> +  UINT64             PhysicalBaseAddress;
>
>   
>
>     /** The base address for GICV interface
>
>         as described by the GICC structure in the
>
>         ACPI Specification.
>
>     */
>
> -  UINT64    GICV;
>
> +  UINT64             GICV;
>
>   
>
>     /** The base address for GICH interface
>
>         as described by the GICC structure in the
>
>         ACPI Specification.
>
>     */
>
> -  UINT64    GICH;
>
> +  UINT64             GICH;
>
>   
>
>     /** The GICV maintenance interrupt
>
>         as described by the GICC structure in the
>
>         ACPI Specification.
>
>     */
>
> -  UINT32    VGICMaintenanceInterrupt;
>
> +  UINT32             VGICMaintenanceInterrupt;
>
>   
>
>     /** The base address for GICR interface
>
>         as described by the GICC structure in the
>
>         ACPI Specification.
>
>     */
>
> -  UINT64    GICRBaseAddress;
>
> +  UINT64             GICRBaseAddress;
>
>   
>
>     /** The MPIDR for the CPU
>
>         as described by the GICC structure in the
>
>         ACPI Specification.
>
>     */
>
> -  UINT64    MPIDR;
>
> +  UINT64             MPIDR;
>
>   
>
>     /** The Processor Power Efficiency class
>
>         as described by the GICC structure in the
>
>         ACPI Specification.
>
>     */
>
> -  UINT8     ProcessorPowerEfficiencyClass;
>
> +  UINT8              ProcessorPowerEfficiencyClass;
>
>   
>
>     /** Statistical Profiling Extension buffer overflow GSIV. Zero if
>
>         unsupported by this processor. This field was introduced in
>
>         ACPI 6.3 (MADT revision 5) and is therefore ignored when
>
>         generating MADT revision 4 or lower.
>
>     */
>
> -  UINT16    SpeOverflowInterrupt;
>
> +  UINT16             SpeOverflowInterrupt;
>
>   
>
>     /** The proximity domain to which the logical processor belongs.
>
>         This field is used to populate the GICC affinity structure
>
>         in the SRAT table.
>
>     */
>
> -  UINT32    ProximityDomain;
>
> +  UINT32             ProximityDomain;
>
>   
>
>     /** The clock domain to which the logical processor belongs.
>
>         This field is used to populate the GICC affinity structure
>
>         in the SRAT table.
>
>     */
>
> -  UINT32    ClockDomain;
>
> +  UINT32             ClockDomain;
>
>   
>
>     /** The GICC Affinity flags field as described by the GICC Affinity structure
>
>         in the SRAT table.
>
>     */
>
> -  UINT32    AffinityFlags;
>
> +  UINT32             AffinityFlags;
>
> +
>
> +  /** Optional field: Reference Token for the Cpc info of this processor.
>
> +      Token identifying a CM_ARM_OBJ_REF structure, itself referencing
>
> +      CM_ARM_CPC_INFO objects.
>
> +  */
>
> +  CM_OBJECT_TOKEN    CpcToken;
>
>   } CM_ARM_GICC_INFO;
>
>   
>
>   /** A structure that describes the
>
> @@ -1070,6 +1077,113 @@ typedef struct CmArmRmrDescriptor {
>
>     UINT64    Length;
>
>   } CM_ARM_MEMORY_RANGE_DESCRIPTOR;
>
>   
>
> +/** A structure that describes the Cpc information.
>
> +
>
> +  Continuous Performance Control is described in DSDT/SSDT and associated
>
> +  to cpus/clusters in the cpu topology.
>
> +
>
> +  Unsupported Optional registers should be encoded with NULL resource
>
> +  Register {(SystemMemory, 0, 0, 0, 0)}
>
> +
>
> +  For values that support Integer or Buffer, integer will be used
>
> +  if buffer is NULL resource.
>
> +  If resource is not NULL then Integer must be 0
>
> +
>
> +  Cf. ACPI 6.4, s8.4.7.1 _CPC (Continuous Performance Control)
>
> +
>
> +  ID: EArmObjCpcInfo
>
> +*/
>
> +typedef struct CmArmCpcInfo {
>
> +  /// The revision number of the _CPC package format.
>
> +  UINT32                                    Revision;
>
> +
>
> +  /// Indicates the highest level of performance the processor
>
> +  /// is theoretically capable of achieving.
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    HighestPerformanceBuffer;
>
> +  UINT32                                    HighestPerformanceInteger;
>
> +
>
> +  /// Indicates the highest sustained performance level of the processor.
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    NominalPerformanceBuffer;
>
> +  UINT32                                    NominalPerformanceInteger;
>
> +
>
> +  /// Indicates the lowest performance level of the processor with non-linear power savings.
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    LowestNonlinearPerformanceBuffer;
>
> +  UINT32                                    LowestNonlinearPerformanceInteger;
>
> +
>
> +  /// Indicates the lowest performance level of the processor..
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    LowestPerformanceBuffer;
>
> +  UINT32                                    LowestPerformanceInteger;
>
> +
>
> +  /// Guaranteed Performance Register Buffer.
>
> +  /// Optional
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    GuaranteedPerformanceRegister;
>
> +
>
> +  /// Desired Performance Register Buffer.
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    DesiredPerformanceRegister;
>
> +
>
> +  /// Minimum Performance Register Buffer.
>
> +  /// Optional
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    MinimumPerformanceRegister;
>
> +
>
> +  /// Maximum Performance Register Buffer.
>
> +  /// Optional
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    MaximumPerformanceRegister;
>
> +
>
> +  /// Performance Reduction Tolerance Register.
>
> +  /// Optional
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    PerformanceReductionToleranceRegister;
>
> +
>
> +  /// Time Window Register.
>
> +  /// Optional
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    TimeWindowRegister;
>
> +
>
> +  /// Counter Wraparound Time
>
> +  /// Optional
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    CounterWraparoundTimeBuffer;
>
> +  UINT32                                    CounterWraparoundTimeInteger;
>
> +
>
> +  /// Reference Performance Counter Register
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    ReferencePerformanceCounterRegister;
>
> +
>
> +  /// Delivered Performance Counter Register
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    DeliveredPerformanceCounterRegister;
>
> +
>
> +  /// Performance Limited Register
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    PerformanceLimitedRegister;
>
> +
>
> +  /// CPPC EnableRegister
>
> +  /// Optional
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    CPPCEnableRegister;
>
> +
>
> +  /// Autonomous Selection Enable
>
> +  /// Optional
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    AutonomousSelectionEnableBuffer;
>
> +  UINT32                                    AutonomousSelectionEnableInteger;
>
> +
>
> +  /// AutonomousActivity-WindowRegister
>
> +  /// Optional
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    AutonomousActivityWindowRegister;
>
> +
>
> +  /// EnergyPerformance-PreferenceRegister
>
> +  /// Optional
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    EnergyPerformancePreferenceRegister;
>
> +
>
> +  /// Reference Performance
>
> +  /// Optional
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    ReferencePerformanceBuffer;
>
> +  UINT32                                    ReferencePerformanceInteger;
>
> +
>
> +  /// Lowest Frequency
>
> +  /// Optional
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    LowestFrequencyBuffer;
>
> +  UINT32                                    LowestFrequencyInteger;
>
> +
>
> +  /// Nominal Frequency
>
> +  /// Optional
>
> +  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE    NominalFrequencyBuffer;
>
> +  UINT32                                    NominalFrequencyInteger;
>
> +} CM_ARM_CPC_INFO;

[SAMI] I think the number of parameters to AmlCreateCpcNode () can be 
reduced if we pass the CPC information using a structure. For this I 
think we can do the following

1. Create a new file called DynamicTablesPkg/Include/Library/AmlCpcInfo.h

2. AmlCpcInfo.h shall define a structure as below

/** A structure that describes the Cpc information.

   Continuous Performance Control is described in DSDT/SSDT and associated
   to cpus/clusters in the cpu topology.
   Unsupported Optional registers should be encoded with NULL resource
   Register {(SystemMemory, 0, 0, 0, 0)}
   For values that support Integer or Buffer, integer will be used
   if buffer is NULL resource.
   If resource is not NULL then Integer must be 0
   Cf. ACPI 6.4, s8.4.7.1 _CPC (Continuous Performance Control)
*/

    typedef struct AmlCpcInfo {

    // Copy all the contents of the CM_ARM_CPC_INFO structure above.

   } AML_CPC_INFO;

3. In DynamicTablesPkg\Include\ArmNameSpaceObjects.h

       #include <Library/AmlCpcInfo.h>

and replace the definition for CM_ARM_CPC_INFO as

/** A structure that describes the Cpc information.

   Continuous Performance Control is described in DSDT/SSDT and associated
   to cpus/clusters in the cpu topology.
   Unsupported Optional registers should be encoded with NULL resource
   Register {(SystemMemory, 0, 0, 0, 0)}
   For values that support Integer or Buffer, integer will be used
   if buffer is NULL resource.
   If resource is not NULL then Integer must be 0
   Cf. ACPI 6.4, s8.4.7.1 _CPC (Continuous Performance Control)
ID:EArmObjCpcInfo
*/
typedefAML_CPC_INFO CM_ARM_CPC_INFO;
[/SAMI]
>
> +
>
>   #pragma pack()
>
>   
>
>   #endif // ARM_NAMESPACE_OBJECTS_H_
>
> diff --git a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
>
> index c1b21d24a4..c7e0d51397 100644
>
> --- a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
>
> +++ b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
>
> @@ -423,6 +423,84 @@ STATIC CONST CM_OBJ_PARSER  CmPciInterruptMapInfoParser[] = {
>
>       ARRAY_SIZE (CmArmGenericInterruptParser) },
>
>   };
>
>   
>
> +/** A parser for EArmObjCpcInfo.
>
> +*/
>
> +STATIC CONST CM_OBJ_PARSER  CmArmCpcInfoParser[] = {
>
> +  { "Revision",                              4,                                               "0x%llx", NULL },
[SAMI] I believe the format specifiers need to be updated to "0x%x" as 
the field width is 32 bits.
>
> +  { "HighestPerformanceBuffer",              sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "HighestPerformanceInteger",             4,                                               "0x%llx", NULL },
>
> +  { "NominalPerformanceBuffer",              sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "NominalPerformanceInteger",             4,                                               "0x%llx", NULL },
>
> +  { "LowestNonlinearPerformanceBuffer",      sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "LowestNonlinearPerformanceInteger",     4,                                               "0x%llx", NULL },
>
> +  { "LowestPerformanceBuffer",               sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "LowestPerformanceInteger",              4,                                               "0x%llx", NULL },
>
> +  { "GuaranteedPerformanceRegister",         sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "DesiredPerformanceRegister",            sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "MinimumPerformanceRegister",            sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "MaximumPerformanceRegister",            sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "PerformanceReductionToleranceRegister", sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "TimeWindowRegister",                    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "CounterWraparoundTimeBuffer",           sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "CounterWraparoundTimeInteger",          4,                                               "0x%llx", NULL },
>
> +  { "ReferencePerformanceCounterRegister",   sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "DeliveredPerformanceCounterRegister",   sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "PerformanceLimitedRegister",            sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "CPPCEnableRegister",                    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "AutonomousSelectionEnableBuffer",       sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "AutonomousSelectionEnableInteger",      4,                                               "0x%llx", NULL },
>
> +  { "AutonomousActivityWindowRegister",      sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "EnergyPerformancePreferenceRegister",   sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "ReferencePerformanceBuffer",            sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "ReferencePerformanceInteger",           4,                                               "0x%llx", NULL },
>
> +  { "LowestFrequencyBuffer",                 sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "LowestFrequencyInteger",                4,                                               "0x%llx", NULL },
>
> +  { "NominalFrequencyBuffer",                sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE),
>
> +    NULL, NULL, AcpiGenericAddressParser,
>
> +    ARRAY_SIZE (AcpiGenericAddressParser) },
>
> +  { "NominalFrequencyInteger",               4,                                               "0x%llx", NULL },
>
> +};
>
> +
>
>   /** A parser for Arm namespace objects.
>
>   */
>
>   STATIC CONST CM_OBJ_PARSER_ARRAY  ArmNamespaceObjectParser[] = {
>
> @@ -501,6 +579,8 @@ STATIC CONST CM_OBJ_PARSER_ARRAY  ArmNamespaceObjectParser[] = {
>
>       ARRAY_SIZE (CmArmPciAddressMapInfoParser) },
>
>     { "EArmObjPciInterruptMapInfo",          CmPciInterruptMapInfoParser,
>
>       ARRAY_SIZE (CmPciInterruptMapInfoParser) },
>
> +  { "EArmObjCpcInfo",                      CmArmCpcInfoParser,
>
> +    ARRAY_SIZE (CmArmCpcInfoParser) },
>
>     { "EArmObjMax",                          NULL,                                  0                                },
>
>   };
>
>   
>

[-- Attachment #2: Type: text/html, Size: 20854 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 2/3] DynamicTablesPkg: AML Code generation to add _CPC entries
  2022-09-15 13:10 ` [PATCH v3 2/3] DynamicTablesPkg: AML Code generation to add _CPC entries Jeff Brasen
@ 2022-09-15 15:16   ` Sami Mujawar
  0 siblings, 0 replies; 7+ messages in thread
From: Sami Mujawar @ 2022-09-15 15:16 UTC (permalink / raw)
  To: Jeff Brasen, devel
  Cc: ardb+tianocore, Alexei.Fedorov, pierre.gondois, nd@arm.com

[-- Attachment #1: Type: text/plain, Size: 37130 bytes --]

Hi Jeff,

Please find my feedback inline marked [SAMI].

Most of my suggestions are with respect to reducing the number of 
parameters in the AmlCreateCpcNod().

Regards,

Sami Mujawar

On 15/09/2022 02:10 pm, Jeff Brasen wrote:
> _CPC entries can describe CPU performance information.
>
> The object is described in ACPI 6.4 s8.4.7.1.
>
> "_CPC (Continuous Performance Control)".
>
>
>
> Add AmlCreateCpcNode() helper function to add _CPC entries to an
>
> existing CPU object.
>
>
>
> Signed-off-by: Jeff Brasen<jbrasen@nvidia.com>
>
> ---
>
>   .../Include/Library/AmlLib/AmlLib.h           | 156 +++++
>
>   .../Common/AmlLib/CodeGen/AmlCodeGen.c        | 543 ++++++++++++++++++
>
>   2 files changed, 699 insertions(+)
>
>
>
> diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
>
> index 39968660f2..3fafa6b0e8 100644
>
> --- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
>
> +++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h

[SAMI] Include <Library/AmlCpcInfo.h> to get the definition for 
AML_CPC_INFO.

>
> @@ -1336,6 +1336,162 @@ AmlAddNameIntegerPackage (
>
>     IN AML_OBJECT_NODE_HANDLE  PackageNode
>
>     );
>
>   
>
> +/** Create a _CPC node.
>
> +
>
> +  Creates and optionally adds the following node
>
> +   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)
>
> +  })
>
> +
>
> +  If resource buffer is NULL then integer will be used.
>
> +
>
> +  Cf. ACPI 6.4, s8.4.7.1 _CPC (Continuous Performance Control)
>
> +
>
> +  @ingroup CodeGenApis
>
> +
>
> +  @param [in]  HighestPerformanceBuffer               If provided, buffer that indicates the highest level
>
> +                                                      of performance the processor.
>
> +  @param [in]  HighestPerformanceInteger              Indicates the highest level of performance the processor,
>
> +                                                      used if buffer is NULL.
>
> +  @param [in]  NominalPerformanceBuffer               If provided buffer that indicates the highest sustained
>
> +                                                      performance level of the processor.
>
> +  @param [in]  NominalPerformanceInteger              Indicates the highest sustained performance level
>
> +                                                      of the processor, used if buffer is NULL.
>
> +  @param [in]  LowestNonlinearPerformanceBuffer       If provided, buffer that indicates the lowest performance level
>
> +                                                      of the processor with non-linear power savings.
>
> +  @param [in]  LowestNonlinearPerformanceInteger      Indicates the lowest performance level of the processor with
>
> +                                                      non-linear power savings, used if buffer is NULL.
>
> +  @param [in]  LowestPerformanceBuffer                If provided, buffer that indicates the
>
> +                                                      lowest performance level of the processor.
>
> +  @param [in]  LowestPerformanceInteger               Indicates the lowest performance level of the processor,
>
> +                                                      used if buffer is NULL.
>
> +  @param [in]  GuaranteedPerformanceRegister          If provided, Guaranteed Performance Register Buffer.
>
> +  @param [in]  DesiredPerformanceRegister             If provided, Desired Performance Register Buffer.
>
> +  @param [in]  MinimumPerformanceRegister             If provided, Minimum Performance Register Buffer.
>
> +  @param [in]  MaximumPerformanceRegister             If provided, Maximum Performance Register Buffer.
>
> +  @param [in]  PerformanceReductionToleranceRegister  If provided, Performance Reduction Tolerance Register.
>
> +  @param [in]  TimeWindowRegister                     If provided, Time Window Register.
>
> +  @param [in]  CounterWraparoundTimeBuffer            If provided, Counter Wraparound Time buffer.
>
> +  @param [in]  CounterWraparoundTimeInteger           Counter Wraparound Time, used if buffer is NULL.
>
> +  @param [in]  ReferencePerformanceCounterRegister    Reference Performance Counter Register.
>
> +  @param [in]  DeliveredPerformanceCounterRegister    Delivered Performance Counter Register.
>
> +  @param [in]  PerformanceLimitedRegister             Performance Limited Register.
>
> +  @param [in]  CPPCEnableRegister                     If provided, CPPC EnableRegister.
>
> +  @param [in]  AutonomousSelectionEnableBuffer        If provided, Autonomous Selection Enable buffer.
>
> +  @param [in]  AutonomousSelectionEnableInteger       Autonomous Selection Enable, used if buffer is NULL.
>
> +  @param [in]  AutonomousActivityWindowRegister       If provided, AutonomousActivity-WindowRegister.
>
> +  @param [in]  EnergyPerformancePreferenceRegister    If provided, EnergyPerformance-PreferenceRegister.
>
> +  @param [in]  ReferencePerformanceBuffer             If provided, Reference Performance buffer.
>
> +  @param [in]  ReferencePerformanceInteger            Reference Performance, used if buffer is NULL.
>
> +  @param [in]  LowestFrequencyBuffer                  If provided, Lowest Frequency buffer.
>
> +  @param [in]  LowestFrequencyInteger                 Lowest Frequency, used if buffer is NULL.
>
> +  @param [in]  NominalFrequencyBuffer                 If provided, NominalFrequencyBuffer buffer.
>
> +  @param [in]  NominalFrequencyInteger                NominalFrequencyBuffer, used if buffer is NULL.
>
> +  @param [in]  ParentNode                             If provided, set ParentNode as the parent
>
> +                                                      of the node created.
>
> +  @param [out] NewCpcNode                             If success and provided, contains the created node.
>
> +
>
> +  @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
>
> +AmlCreateCpcNode (

[SAMI] The number of parameters to this function can be reduced by 
passing a pointer to AML_CPC_INFO.

So the new prototype for this function can be made as below:

EFI_STATUS
EFIAPI
AmlCreateCpcNode (
   IN AML_CPC_INFO             *CpcInfo,
   IN  AML_NODE_HANDLE         ParentNode   OPTIONAL,
   OUT AML_OBJECT_NODE_HANDLE  *NewCpcNode   OPTIONAL
   );
[/SAMI]

>
> +  /// The revision number of the _CPC package format.
>
> +  IN  UINT32  Revision,
>
> +  /// Indicates the highest level of performance the processor
>
> +  /// is theoretically capable of achieving.
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *HighestPerformanceBuffer OPTIONAL,
>
> +  IN  UINT32                                  HighestPerformanceInteger,
>
> +  /// Indicates the highest sustained performance level of the processor.
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE   *NominalPerformanceBuffer OPTIONAL,
>
> +  IN UINT32                                   NominalPerformanceInteger,
>
> +  /// Indicates the lowest performance level of the processor with non-linear power savings.
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *LowestNonlinearPerformanceBuffer OPTIONAL,
>
> +  IN UINT32                                   LowestNonlinearPerformanceInteger,
>
> +  /// Indicates the lowest performance level of the processor..
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *LowestPerformanceBuffer OPTIONAL,
>
> +  IN  UINT32                                  LowestPerformanceInteger,
>
> +  /// Guaranteed Performance Register Buffer.
>
> +  /// Optional
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *GuaranteedPerformanceRegister OPTIONAL,
>
> +  /// Desired Performance Register Buffer.
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *DesiredPerformanceRegister,
>
> +  /// Minimum Performance Register Buffer.
>
> +  /// Optional
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *MinimumPerformanceRegister OPTIONAL,
>
> +  /// Maximum Performance Register Buffer.
>
> +  /// Optional
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *MaximumPerformanceRegister OPTIONAL,
>
> +  /// Performance Reduction Tolerance Register.
>
> +  /// Optional
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *PerformanceReductionToleranceRegister OPTIONAL,
>
> +  /// Time Window Register.
>
> +  /// Optional
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *TimeWindowRegister OPTIONAL,
>
> +  /// Counter Wraparound Time
>
> +  /// Optional
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *CounterWraparoundTimeBuffer OPTIONAL,
>
> +  IN  UINT32                                  CounterWraparoundTimeInteger,
>
> +  /// Reference Performance Counter Register
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *ReferencePerformanceCounterRegister,
>
> +  /// Delivered Performance Counter Register
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *DeliveredPerformanceCounterRegister,
>
> +  /// Performance Limited Register
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *PerformanceLimitedRegister,
>
> +  /// CPPC EnableRegister
>
> +  /// Optional
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *CPPCEnableRegister OPTIONAL,
>
> +  /// Autonomous Selection Enable
>
> +  /// Optional
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *AutonomousSelectionEnableBuffer OPTIONAL,
>
> +  IN  UINT32                                  AutonomousSelectionEnableInteger,
>
> +  /// AutonomousActivity-WindowRegister
>
> +  /// Optional
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *AutonomousActivityWindowRegister OPTIONAL,
>
> +  /// EnergyPerformance-PreferenceRegister
>
> +  /// Optional
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *EnergyPerformancePreferenceRegister OPTIONAL,
>
> +  /// Reference Performance
>
> +  /// Optional
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *ReferencePerformanceBuffer OPTIONAL,
>
> +  IN  UINT32                                  ReferencePerformanceInteger,
>
> +  /// Lowest Frequency
>
> +  /// Optional
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *LowestFrequencyBuffer OPTIONAL,
>
> +  IN  UINT32                                  LowestFrequencyInteger,
>
> +  /// Nominal Frequency
>
> +  /// Optional
>
> +  IN  EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *NominalFrequencyBuffer OPTIONAL,
>
> +  IN  UINT32                                  NominalFrequencyInteger,
>
> +  IN  AML_NODE_HANDLE                         ParentNode   OPTIONAL,
>
> +  OUT AML_OBJECT_NODE_HANDLE                  *NewCpcNode   OPTIONAL
>
> +  );
>
> +
>
>   // DEPRECATED APIS
>
>   #ifndef DISABLE_NEW_DEPRECATED_INTERFACES
>
>   
>
> diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
>
> index 5fb39d077b..42f0d0002c 100644
>
> --- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
>
> +++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
[SAMI] Include  <Library/AmlCpcInfo.h>
>
> @@ -2850,3 +2850,546 @@ error_handler:
>
>   
>
>     return Status;
>
>   }
>
> +
>
> +/** Adds a register to the package
>
> +
>
> +  @ingroup CodeGenApis
>
> +
>
> +  @param [in]  Register     If provided, register that will be added to package.
>
> +                            otherwise NULL register will be added
>
> +  @param [in]  PackageNode  Package to add value to
>
> +
>
> +  @retval EFI_SUCCESS             The function completed successfully.
>
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
>
> +  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +EFIAPI
>
> +AmlAddRegisterToPackage (
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *Register OPTIONAL,
>
> +  IN AML_OBJECT_NODE_HANDLE                  PackageNode
>
> +  )
>
> +{
>
> +  EFI_STATUS              Status;
>
> +  AML_DATA_NODE_HANDLE    RdNode;
>
> +  AML_OBJECT_NODE_HANDLE  ResourceTemplateNode;
>
> +
>
> +  RdNode = NULL;
>
> +
>
> +  Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode);
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    return Status;
>
> +  }
>
> +
>
> +  if (Register != NULL) {
>
> +    Status = AmlCodeGenRdRegister (
>
> +               Register->AddressSpaceId,
>
> +               Register->RegisterBitWidth,
>
> +               Register->RegisterBitOffset,
>
> +               Register->Address,
>
> +               Register->AccessSize,
>
> +               NULL,
>
> +               &RdNode
>
> +               );
>
> +  } else {
>
> +    Status = AmlCodeGenRdRegister (
>
> +               EFI_ACPI_6_4_SYSTEM_MEMORY,
>
> +               0,
>
> +               0,
>
> +               0,
>
> +               0,
>
> +               NULL,
>
> +               &RdNode
>
> +               );
>
> +  }
>
> +
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAppendRdNode (ResourceTemplateNode, RdNode);
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  RdNode = NULL;
>
> +
>
> +  Status = AmlVarListAddTail (
>
> +             (AML_NODE_HANDLE)PackageNode,
>
> +             (AML_NODE_HANDLE)ResourceTemplateNode
>
> +             );
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  return Status;
>
> +
>
> +error_handler:
>
> +  if (RdNode != NULL) {
>
> +    AmlDeleteTree ((AML_NODE_HANDLE)RdNode);
>
> +  }
>
> +
>
> +  if (ResourceTemplateNode != NULL) {
>
> +    AmlDeleteTree ((AML_NODE_HANDLE)ResourceTemplateNode);
>
> +  }
>
> +
>
> +  return Status;
>
> +}
>
> +
[SAMI] Move IsNullGenericAddress() from patch 3/3 file 
DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.cover 
here.

[/SAMI]
>
> +/** Adds an integer or register to the package
>
> +
>
> +  @ingroup CodeGenApis
>
> +
>
> +  @param [in]  Register     If provided, register that will be added to package
>
> +  @param [in]  Integer      If Register is NULL, integer that will be added to the package
>
> +  @param [in]  PackageNode  Package to add value to
>
> +
>
> +  @retval EFI_SUCCESS             The function completed successfully.
>
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
>
> +  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +EFIAPI
>
> +AmlAddRegisterOrIntegerToPackage (
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *Register OPTIONAL,
>
> +  IN UINT32                                  Integer,
>
> +  IN AML_OBJECT_NODE_HANDLE                  PackageNode
>
> +  )
>
> +{
>
> +  EFI_STATUS              Status;
>
> +  AML_OBJECT_NODE_HANDLE  IntegerNode;
>
> +
>
> +  IntegerNode = NULL;
>
> +
>
> +  if (Register != NULL) {

[SAMI] Modify the above check to

if((Register != NULL) && !IsNullGenericAddress (Register)) {
[/SAMI]

>
> +    Status = AmlAddRegisterToPackage (Register, PackageNode);
>
> +  } else {
>
> +    Status = AmlCodeGenInteger (Integer, &IntegerNode);
>
> +    if (EFI_ERROR (Status)) {
>
> +      ASSERT_EFI_ERROR (Status);
>
> +      return Status;
>
> +    }
>
> +
>
> +    Status = AmlVarListAddTail (
>
> +               (AML_NODE_HANDLE)PackageNode,
>
> +               (AML_NODE_HANDLE)IntegerNode
>
> +               );
>
> +  }
>
> +
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    if (IntegerNode != NULL) {
>
> +      AmlDeleteTree ((AML_NODE_HANDLE)IntegerNode);
>
> +    }
>
> +  }
>
> +
>
> +  return Status;
>
> +}
>
> +
>
> +/** Create a _CPC node.
>
> +
>
> +  Creates and optionally adds the following node
>
> +   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)
>
> +  })
>
> +
>
> +  If resource buffer is NULL then integer will be used.
>
> +
>
> +  Cf. ACPI 6.4, s8.4.7.1 _CPC (Continuous Performance Control)
>
> +
>
> +  @ingroup CodeGenApis
>
> +
>
> +  @param [in]  HighestPerformanceBuffer               If provided, buffer that indicates the highest level
>
> +                                                      of performance the processor.
>
> +  @param [in]  HighestPerformanceInteger              Indicates the highest level of performance the processor,
>
> +                                                      used if buffer is NULL.
>
> +  @param [in]  NominalPerformanceBuffer               If provided buffer that indicates the highest sustained
>
> +                                                      performance level of the processor.
>
> +  @param [in]  NominalPerformanceInteger              Indicates the highest sustained performance level
>
> +                                                      of the processor, used if buffer is NULL.
>
> +  @param [in]  LowestNonlinearPerformanceBuffer       If provided, buffer that indicates the lowest performance level
>
> +                                                      of the processor with non-linear power savings.
>
> +  @param [in]  LowestNonlinearPerformanceInteger      Indicates the lowest performance level of the processor with
>
> +                                                      non-linear power savings, used if buffer is NULL.
>
> +  @param [in]  LowestPerformanceBuffer                If provided, buffer that indicates the
>
> +                                                      lowest performance level of the processor.
>
> +  @param [in]  LowestPerformanceInteger               Indicates the lowest performance level of the processor,
>
> +                                                      used if buffer is NULL.
>
> +  @param [in]  GuaranteedPerformanceRegister          If provided, Guaranteed Performance Register Buffer.
>
> +  @param [in]  DesiredPerformanceRegister             If provided, Desired Performance Register Buffer.
>
> +  @param [in]  MinimumPerformanceRegister             If provided, Minimum Performance Register Buffer.
>
> +  @param [in]  MaximumPerformanceRegister             If provided, Maximum Performance Register Buffer.
>
> +  @param [in]  PerformanceReductionToleranceRegister  If provided, Performance Reduction Tolerance Register.
>
> +  @param [in]  TimeWindowRegister                     If provided, Time Window Register.
>
> +  @param [in]  CounterWraparoundTimeBuffer            If provided, Counter Wraparound Time buffer.
>
> +  @param [in]  CounterWraparoundTimeInteger           Counter Wraparound Time, used if buffer is NULL.
>
> +  @param [in]  ReferencePerformanceCounterRegister    Reference Performance Counter Register.
>
> +  @param [in]  DeliveredPerformanceCounterRegister    Delivered Performance Counter Register.
>
> +  @param [in]  PerformanceLimitedRegister             Performance Limited Register.
>
> +  @param [in]  CPPCEnableRegister                     If provided, CPPC EnableRegister.
>
> +  @param [in]  AutonomousSelectionEnableBuffer        If provided, Autonomous Selection Enable buffer.
>
> +  @param [in]  AutonomousSelectionEnableInteger       Autonomous Selection Enable, used if buffer is NULL.
>
> +  @param [in]  AutonomousActivityWindowRegister       If provided, AutonomousActivity-WindowRegister.
>
> +  @param [in]  EnergyPerformancePreferenceRegister    If provided, EnergyPerformance-PreferenceRegister.
>
> +  @param [in]  ReferencePerformanceBuffer             If provided, Reference Performance buffer.
>
> +  @param [in]  ReferencePerformanceInteger            Reference Performance, used if buffer is NULL.
>
> +  @param [in]  LowestFrequencyBuffer                  If provided, Lowest Frequency buffer.
>
> +  @param [in]  LowestFrequencyInteger                 Lowest Frequency, used if buffer is NULL.
>
> +  @param [in]  NominalFrequencyBuffer                 If provided, NominalFrequencyBuffer buffer.
>
> +  @param [in]  NominalFrequencyInteger                NominalFrequencyBuffer, used if buffer is NULL.
>
> +  @param [in]  ParentNode                             If provided, set ParentNode as the parent
>
> +                                                      of the node created.
>
> +  @param [out] NewCpcNode                             If success and provided, contains the created node.
>
> +
>
> +  @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
>
> +AmlCreateCpcNode (
>
> +  /// The revision number of the _CPC package format.
>
> +  IN  UINT32  Revision,
>
> +  /// Indicates the highest level of performance the processor
>
> +  /// is theoretically capable of achieving.
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *HighestPerformanceBuffer OPTIONAL,
>
> +  IN UINT32                                  HighestPerformanceInteger,
>
> +  /// Indicates the highest sustained performance level of the processor.
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *NominalPerformanceBuffer OPTIONAL,
>
> +  IN UINT32                                  NominalPerformanceInteger,
>
> +  /// Indicates the lowest performance level of the processor with non-linear power savings.
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *LowestNonlinearPerformanceBuffer OPTIONAL,
>
> +  IN UINT32                                  LowestNonlinearPerformanceInteger,
>
> +  /// Indicates the lowest performance level of the processor..
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *LowestPerformanceBuffer OPTIONAL,
>
> +  IN UINT32                                  LowestPerformanceInteger,
>
> +  /// Guaranteed Performance Register Buffer.
>
> +  /// Optional
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *GuaranteedPerformanceRegister OPTIONAL,
>
> +  /// Desired Performance Register Buffer.
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *DesiredPerformanceRegister,
>
> +  /// Minimum Performance Register Buffer.
>
> +  /// Optional
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *MinimumPerformanceRegister OPTIONAL,
>
> +  /// Maximum Performance Register Buffer.
>
> +  /// Optional
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *MaximumPerformanceRegister OPTIONAL,
>
> +  /// Performance Reduction Tolerance Register.
>
> +  /// Optional
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *PerformanceReductionToleranceRegister OPTIONAL,
>
> +  /// Time Window Register.
>
> +  /// Optional
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *TimeWindowRegister OPTIONAL,
>
> +  /// Counter Wraparound Time
>
> +  /// Optional
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *CounterWraparoundTimeBuffer OPTIONAL,
>
> +  IN UINT32                                  CounterWraparoundTimeInteger,
>
> +  /// Reference Performance Counter Register
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *ReferencePerformanceCounterRegister,
>
> +  /// Delivered Performance Counter Register
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *DeliveredPerformanceCounterRegister,
>
> +  /// Performance Limited Register
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *PerformanceLimitedRegister,
>
> +  /// CPPC EnableRegister
>
> +  /// Optional
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *CPPCEnableRegister OPTIONAL,
>
> +  /// Autonomous Selection Enable
>
> +  /// Optional
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *AutonomousSelectionEnableBuffer OPTIONAL,
>
> +  IN UINT32                                  AutonomousSelectionEnableInteger,
>
> +  /// AutonomousActivity-WindowRegister
>
> +  /// Optional
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *AutonomousActivityWindowRegister OPTIONAL,
>
> +  /// EnergyPerformance-PreferenceRegister
>
> +  /// Optional
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *EnergyPerformancePreferenceRegister OPTIONAL,
>
> +  /// Reference Performance
>
> +  /// Optional
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *ReferencePerformanceBuffer OPTIONAL,
>
> +  IN UINT32                                  ReferencePerformanceInteger,
>
> +  /// Lowest Frequency
>
> +  /// Optional
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *LowestFrequencyBuffer OPTIONAL,
>
> +  IN UINT32                                  LowestFrequencyInteger,
>
> +  /// Nominal Frequency
>
> +  /// Optional
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *NominalFrequencyBuffer OPTIONAL,
>
> +  IN UINT32                                  NominalFrequencyInteger,
>
> +  IN AML_NODE_HANDLE                         ParentNode OPTIONAL,
>
> +  OUT AML_OBJECT_NODE_HANDLE                 *NewCpcNode OPTIONAL
>
> +  )

[SAMI] The number of parameters to this function can be reduced

EFI_STATUS
EFIAPI
AmlCreateCpcNode (
   IN AML_CPC_INFO             *CpcInfo,
   IN  AML_NODE_HANDLE         ParentNode   OPTIONAL,
   OUT AML_OBJECT_NODE_HANDLE  *NewCpcNode   OPTIONAL
   )
{
[/SAMI]

>
> +{
>
> +  EFI_STATUS              Status;
>
> +  AML_OBJECT_NODE_HANDLE  CpcNode;
>
> +  AML_OBJECT_NODE_HANDLE  CpcPackage;
>
> +  UINT32                  NumberOfEntries;
>
> +
>
> +  // Revision 3 per ACPI 6.4 specification
>
> +  if (Revision == 3) {
>
> +    // NumEntries 23 per ACPI 6.4 specification
>
> +    NumberOfEntries = 23;
>
> +  } else {
>
> +    ASSERT (0);
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  if (((HighestPerformanceBuffer == NULL) && (HighestPerformanceInteger == 0)) ||
>
> +      ((NominalPerformanceBuffer == NULL) && (NominalPerformanceInteger == 0)) ||
>
> +      ((LowestNonlinearPerformanceBuffer == NULL) && (LowestNonlinearPerformanceInteger == 0)) ||
>
> +      ((LowestPerformanceBuffer == NULL) && (LowestPerformanceInteger == 0)) ||
>
> +      (DesiredPerformanceRegister == NULL)    ||
>
> +      (ReferencePerformanceCounterRegister == NULL)    ||
>
> +      (DeliveredPerformanceCounterRegister == NULL)    ||
>
> +      (PerformanceLimitedRegister == NULL)             ||

[SAMI] Checks can be reduced to

if((CpcInfo == NULL) ||
       ((ParentNode == NULL) && (NewCpcNode == NULL)))

[/SAMI]
>
> +      ((ParentNode == NULL) && (NewCpcNode == NULL)))
>
> +  {
>
> +    ASSERT (0);
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  CpcPackage = NULL;
>
> +
>
> +  Status = AmlCodeGenNamePackage ("_CPC", NULL, &CpcNode);
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    return Status;
>
> +  }
>
> +
>
> +  // Get the Package object node of the _CPC node,
>
> +  // which is the 2nd fixed argument (i.e. index 1).
>
> +  CpcPackage = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (
>
> +                                         CpcNode,
>
> +                                         EAmlParseIndexTerm1
>
> +                                         );
>
> +  if ((CpcPackage == NULL)                                              ||
>
> +      (AmlGetNodeType ((AML_NODE_HANDLE)CpcPackage) != EAmlNodeObject)  ||
>
> +      (!AmlNodeHasOpCode (CpcPackage, AML_PACKAGE_OP, 0)))
>
> +  {
>
> +    ASSERT (0);
>
> +    Status = EFI_INVALID_PARAMETER;
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterOrIntegerToPackage (
>
> +             NULL,
>
> +             NumberOfEntries,
>
> +             CpcPackage
>
> +             );
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterOrIntegerToPackage (
>
> +             NULL,
>
> +             Revision,
>
> +             CpcPackage
>
> +             );
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterOrIntegerToPackage (
>
> +             HighestPerformanceBuffer,
>
> +             HighestPerformanceInteger,
[SAMI] Parameters need updating as

+&CpcInfo->HighestPerformanceBuffer,

+CpcInfo->HighestPerformanceInteger,
Similar changes at other places in this file.

[/SAMI]
>
> +             CpcPackage
>
> +             );
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterOrIntegerToPackage (
>
> +             NominalPerformanceBuffer,
>
> +             NominalPerformanceInteger,
>
> +             CpcPackage
>
> +             );
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterOrIntegerToPackage (
>
> +             LowestNonlinearPerformanceBuffer,
>
> +             LowestNonlinearPerformanceInteger,
>
> +             CpcPackage
>
> +             );
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterOrIntegerToPackage (
>
> +             LowestPerformanceBuffer,
>
> +             LowestPerformanceInteger,
>
> +             CpcPackage
>
> +             );
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterToPackage (GuaranteedPerformanceRegister, CpcPackage);
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterToPackage (DesiredPerformanceRegister, CpcPackage);
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterToPackage (MinimumPerformanceRegister, CpcPackage);
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterToPackage (MaximumPerformanceRegister, CpcPackage);
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterToPackage (PerformanceReductionToleranceRegister, CpcPackage);
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterToPackage (TimeWindowRegister, CpcPackage);
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterOrIntegerToPackage (
>
> +             CounterWraparoundTimeBuffer,
>
> +             CounterWraparoundTimeInteger,
>
> +             CpcPackage
>
> +             );
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterToPackage (ReferencePerformanceCounterRegister, CpcPackage);
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterToPackage (DeliveredPerformanceCounterRegister, CpcPackage);
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterToPackage (PerformanceLimitedRegister, CpcPackage);
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterToPackage (CPPCEnableRegister, CpcPackage);
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterOrIntegerToPackage (
>
> +             AutonomousSelectionEnableBuffer,
>
> +             AutonomousSelectionEnableInteger,
>
> +             CpcPackage
>
> +             );
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterToPackage (AutonomousActivityWindowRegister, CpcPackage);
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterToPackage (EnergyPerformancePreferenceRegister, CpcPackage);
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterOrIntegerToPackage (
>
> +             ReferencePerformanceBuffer,
>
> +             ReferencePerformanceInteger,
>
> +             CpcPackage
>
> +             );
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterOrIntegerToPackage (
>
> +             LowestFrequencyBuffer,
>
> +             LowestFrequencyInteger,
>
> +             CpcPackage
>
> +             );
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = AmlAddRegisterOrIntegerToPackage (
>
> +             NominalFrequencyBuffer,
>
> +             NominalFrequencyInteger,
>
> +             CpcPackage
>
> +             );
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  Status = LinkNode (CpcNode, ParentNode, NewCpcNode);
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT_EFI_ERROR (Status);
>
> +    goto error_handler;
>
> +  }
>
> +
>
> +  return Status;
>
> +
>
> +error_handler:
>
> +  AmlDeleteTree ((AML_NODE_HANDLE)CpcNode);
>
> +  return Status;
>
> +}
>

[-- Attachment #2: Type: text/html, Size: 40396 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 3/3] DynamicTablesPkg: SSDT CPU _CPC generator
  2022-09-15 13:10 ` [PATCH v3 3/3] DynamicTablesPkg: SSDT CPU _CPC generator Jeff Brasen
@ 2022-09-15 15:16   ` Sami Mujawar
  0 siblings, 0 replies; 7+ messages in thread
From: Sami Mujawar @ 2022-09-15 15:16 UTC (permalink / raw)
  To: Jeff Brasen, devel
  Cc: ardb+tianocore, Alexei.Fedorov, pierre.gondois, nd@arm.com

Hi Jeff,

Please find my inputs inline marked [SAMI].

Regards,

Sami Mujawar

On 15/09/2022 02:10 pm, Jeff Brasen wrote:
> Add code to use a token attached to GICC to generate _CPC object on cpus.
>
>
>
> Signed-off-by: Jeff Brasen <jbrasen@nvidia.com>
>
> ---
>
>   .../SsdtCpuTopologyGenerator.c                | 223 +++++++++++++++++-
>
>   1 file changed, 217 insertions(+), 6 deletions(-)
>
>
>
> diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c
>
> index 8561f48e1f..5d41d57064 100644
>
> --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c
>
> +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c
>
> @@ -76,6 +76,16 @@ GET_OBJECT_LIST (
>
>     CM_ARM_LPI_INFO
>
>     );
>
>   
>
> +/**
>
> +  This macro expands to a function that retrieves the CPC
>
> +  information from the Configuration Manager.
>
> +*/
>
> +GET_OBJECT_LIST (
>
> +  EObjNameSpaceArm,
>
> +  EArmObjCpcInfo,
>
> +  CM_ARM_CPC_INFO
>
> +  );
>
> +
>
>   /** Initialize the TokenTable.
>
>   
>
>     One entry should be allocated for each CM_ARM_PROC_HIERARCHY_INFO
>
> @@ -229,6 +239,183 @@ WriteAslName (
>
>     return EFI_SUCCESS;
>
>   }
>
>   
>
> +/** Utility function to check if generic address points to NULL
>
> +
>
> +  @param [in]  Address  Pointer to the Generic address
>
> +
>
> +  @retval TRUE          Address is system memory with an Address of 0.
>
> +  @retval FALSE         Address does not point to NULL.
>
> +**/
>
> +STATIC
>
> +BOOLEAN
>
> +EFIAPI
>
> +IsNullGenericAddress (
[SAMI] Move this function to 
DynamicTablesPkg\Library\Common\AmlLib\CodeGen\AmlCodeGen.c
>
> +  IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE  *Address
>
> +  )
>
> +{
>
> +  if ((Address == NULL) ||
>
> +      ((Address->AddressSpaceId == EFI_ACPI_6_4_SYSTEM_MEMORY) &&
>
> +       (Address->Address == 0x0)))
>
> +  {
>
> +    return TRUE;
>
> +  }
>
> +
>
> +  return FALSE;
>
> +}
>
> +
>
> +/** 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]  ProcHierarchyNodeInfo  CM_ARM_PROC_HIERARCHY_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.
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +EFIAPI
>
> +CreateAmlCpcNode (
>
> +  IN  ACPI_CPU_TOPOLOGY_GENERATOR                         *Generator,
>
> +  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol,
>
> +  IN    CM_ARM_GICC_INFO                                  *GicCInfo,
>
> +  IN  AML_OBJECT_NODE_HANDLE                              *Node
>
> +  )
>
> +{
>
> +  EFI_STATUS       Status;
>
> +  CM_ARM_CPC_INFO  *CpcInfo;
>
> +
>
> +  Status = GetEArmObjCpcInfo (
>
> +             CfgMgrProtocol,
>
> +             GicCInfo->CpcToken,
>
> +             &CpcInfo,
>
> +             NULL
>
> +             );
>
> +  if (EFI_ERROR (Status)) {
>
> +    ASSERT (0);
>
> +    return Status;
>
> +  }
>
> +
>
> +  Status = AmlCreateCpcNode (
[SAMI] The number of parameters to this functions can be reduced to just 
pass CpcInfo.
>
> +             CpcInfo->Revision,
>
> +             IsNullGenericAddress (&CpcInfo->HighestPerformanceBuffer) ?
>
> +             NULL :
>
> +             &CpcInfo->HighestPerformanceBuffer,
>
> +             CpcInfo->HighestPerformanceInteger,
>
> +             IsNullGenericAddress (&CpcInfo->NominalPerformanceBuffer) ?
>
> +             NULL :
>
> +             &CpcInfo->NominalPerformanceBuffer,
>
> +             CpcInfo->NominalPerformanceInteger,
>
> +             IsNullGenericAddress (&CpcInfo->LowestNonlinearPerformanceBuffer) ?
>
> +             NULL :
>
> +             &CpcInfo->LowestNonlinearPerformanceBuffer,
>
> +             CpcInfo->LowestNonlinearPerformanceInteger,
>
> +             IsNullGenericAddress (&CpcInfo->LowestPerformanceBuffer) ?
>
> +             NULL :
>
> +             &CpcInfo->LowestPerformanceBuffer,
>
> +             CpcInfo->LowestPerformanceInteger,
>
> +             IsNullGenericAddress (&CpcInfo->GuaranteedPerformanceRegister) ?
>
> +             NULL :
>
> +             &CpcInfo->GuaranteedPerformanceRegister,
>
> +             IsNullGenericAddress (&CpcInfo->DesiredPerformanceRegister) ?
>
> +             NULL :
>
> +             &CpcInfo->DesiredPerformanceRegister,
>
> +             IsNullGenericAddress (&CpcInfo->MinimumPerformanceRegister) ?
>
> +             NULL :
>
> +             &CpcInfo->MinimumPerformanceRegister,
>
> +             IsNullGenericAddress (&CpcInfo->MaximumPerformanceRegister) ?
>
> +             NULL :
>
> +             &CpcInfo->MaximumPerformanceRegister,
>
> +             IsNullGenericAddress (&CpcInfo->PerformanceReductionToleranceRegister) ?
>
> +             NULL :
>
> +             &CpcInfo->PerformanceReductionToleranceRegister,
>
> +             IsNullGenericAddress (&CpcInfo->TimeWindowRegister) ?
>
> +             NULL :
>
> +             &CpcInfo->TimeWindowRegister,
>
> +             IsNullGenericAddress (&CpcInfo->CounterWraparoundTimeBuffer) ?
>
> +             NULL :
>
> +             &CpcInfo->CounterWraparoundTimeBuffer,
>
> +             CpcInfo->CounterWraparoundTimeInteger,
>
> +             &CpcInfo->ReferencePerformanceCounterRegister,
>
> +             &CpcInfo->DeliveredPerformanceCounterRegister,
>
> +             &CpcInfo->PerformanceLimitedRegister,
>
> +             IsNullGenericAddress (&CpcInfo->CPPCEnableRegister) ?
>
> +             NULL :
>
> +             &CpcInfo->CPPCEnableRegister,
>
> +             IsNullGenericAddress (&CpcInfo->AutonomousSelectionEnableBuffer) ?
>
> +             NULL :
>
> +             &CpcInfo->AutonomousSelectionEnableBuffer,
>
> +             CpcInfo->AutonomousSelectionEnableInteger,
>
> +             IsNullGenericAddress (&CpcInfo->AutonomousActivityWindowRegister) ?
>
> +             NULL :
>
> +             &CpcInfo->AutonomousActivityWindowRegister,
>
> +             IsNullGenericAddress (&CpcInfo->EnergyPerformancePreferenceRegister) ?
>
> +             NULL :
>
> +             &CpcInfo->EnergyPerformancePreferenceRegister,
>
> +             IsNullGenericAddress (&CpcInfo->ReferencePerformanceBuffer) ?
>
> +             NULL :
>
> +             &CpcInfo->ReferencePerformanceBuffer,
>
> +             CpcInfo->ReferencePerformanceInteger,
>
> +             IsNullGenericAddress (&CpcInfo->LowestFrequencyBuffer) ?
>
> +             NULL :
>
> +             &CpcInfo->LowestFrequencyBuffer,
>
> +             CpcInfo->LowestFrequencyInteger,
>
> +             IsNullGenericAddress (&CpcInfo->NominalFrequencyBuffer) ?
>
> +             NULL :
>
> +             &CpcInfo->NominalFrequencyBuffer,
>
> +             CpcInfo->NominalFrequencyInteger,
>
> +             Node,
>
> +             NULL
>
> +             );
>
> +  ASSERT_EFI_ERROR (Status);
>
> +  return Status;
>
> +}
>
> +
>
>   /** Create and add an _LPI method to Cpu/Cluster Node.
>
>   
>
>     For instance, transform an AML node from:
>
> @@ -581,7 +768,20 @@ CreateAmlCpuFromProcHierarchy (
>
>     // CM_ARM_PROC_HIERARCHY_INFO, create an _LPI method returning them.
>
>     if (ProcHierarchyNodeInfo->LpiToken != CM_NULL_TOKEN) {
>
>       Status = CreateAmlLpiMethod (Generator, ProcHierarchyNodeInfo, CpuNode);
>
> -    ASSERT_EFI_ERROR (Status);
>
> +    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->CpcToken != CM_NULL_TOKEN) {
>
> +    Status = CreateAmlCpcNode (Generator, CfgMgrProtocol, GicCInfo, CpuNode);
>
> +    if (EFI_ERROR (Status)) {
>
> +      ASSERT_EFI_ERROR (Status);
>
> +      return Status;
>
> +    }
>
>     }
>
>   
>
>     return Status;
>
> @@ -934,10 +1134,11 @@ CreateTopologyFromGicC (
>
>     IN        AML_OBJECT_NODE_HANDLE                        ScopeNode
>
>     )
>
>   {
>
> -  EFI_STATUS        Status;
>
> -  CM_ARM_GICC_INFO  *GicCInfo;
>
> -  UINT32            GicCInfoCount;
>
> -  UINT32            Index;
>
> +  EFI_STATUS              Status;
>
> +  CM_ARM_GICC_INFO        *GicCInfo;
>
> +  UINT32                  GicCInfoCount;
>
> +  UINT32                  Index;
>
> +  AML_OBJECT_NODE_HANDLE  CpuNode;
>
>   
>
>     ASSERT (Generator != NULL);
>
>     ASSERT (CfgMgrProtocol != NULL);
>
> @@ -961,12 +1162,22 @@ CreateTopologyFromGicC (
>
>                  ScopeNode,
>
>                  &GicCInfo[Index],
>
>                  Index,
>
> -               NULL
>
> +               &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->CpcToken != CM_NULL_TOKEN) {
>
> +      Status = CreateAmlCpcNode (Generator, CfgMgrProtocol, &GicCInfo[Index], CpuNode);
>
> +      if (EFI_ERROR (Status)) {
>
> +        ASSERT_EFI_ERROR (Status);
>
> +        break;
>
> +      }
>
> +    }
>
>     } // for
>
>   
>
>     return Status;
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-09-15 15:17 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-09-15 13:10 [PATCH v3 0/3] DynamicTablesPkg: _CPC support Jeff Brasen
2022-09-15 13:10 ` [PATCH v3 1/3] DynamicTablesPkg: Add CM_ARM_CPC_INFO object Jeff Brasen
2022-09-15 15:14   ` Sami Mujawar
2022-09-15 13:10 ` [PATCH v3 2/3] DynamicTablesPkg: AML Code generation to add _CPC entries Jeff Brasen
2022-09-15 15:16   ` Sami Mujawar
2022-09-15 13:10 ` [PATCH v3 3/3] DynamicTablesPkg: SSDT CPU _CPC generator Jeff Brasen
2022-09-15 15:16   ` Sami Mujawar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox