[edk2,edk2-platforms,v4,17/31] Hisilicon/Hi1620: Add ACPI PPTT table

Message ID 20180823160743.45638-18-ming.huang@linaro.org
State Superseded
Headers show
Series
  • Upload for D06 platform
Related show

Commit Message

Ming Huang Aug. 23, 2018, 4:07 p.m.
From: Heyi Guo <heyi.guo@linaro.org>


This driver fetches information from MADT,  so it is adaptable for
partial good and 1P/2P, since MADT is updated for different
configurations by certain mechanism.

Since L2 cache is also private resource of core, so we need to set the
next level of cache for L1I and L1D, which is important for OS to
parse cache hierarchy.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ming Huang <ming.huang@linaro.org>

Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>

---
 Silicon/Hisilicon/Hi1620/Pptt/Pptt.inf |  48 ++
 Silicon/Hisilicon/Hi1620/Pptt/Pptt.h   |  68 +++
 Silicon/Hisilicon/Hi1620/Pptt/Pptt.c   | 543 ++++++++++++++++++++
 3 files changed, 659 insertions(+)

-- 
2.18.0

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Patch

diff --git a/Silicon/Hisilicon/Hi1620/Pptt/Pptt.inf b/Silicon/Hisilicon/Hi1620/Pptt/Pptt.inf
new file mode 100644
index 0000000000..f8a5ed33a4
--- /dev/null
+++ b/Silicon/Hisilicon/Hi1620/Pptt/Pptt.inf
@@ -0,0 +1,48 @@ 
+/** @file
+*
+*  Copyright (c) 2018, Hisilicon Limited. All rights reserved.
+*  Copyright (c) 2018, Linaro Limited. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+*  Based on the files under Platform/ARM/JunoPkg/AcpiTables/
+*
+**/
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = AcpiPptt
+  FILE_GUID                      = 65766562-49e7-11e8-817f-286ed489ee9b
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = PpttEntryPoint
+
+[Sources.common]
+  Pptt.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/Hisilicon/HisiPkg.dec
+
+[LibraryClasses]
+  ArmLib
+  BaseMemoryLib
+  DebugLib
+  HobLib
+  UefiDriverEntryPoint
+  UefiRuntimeServicesTableLib
+
+[Protocols]
+  gEfiAcpiSdtProtocolGuid                       ## PROTOCOL ALWAYS_CONSUMED
+  gEfiAcpiTableProtocolGuid                     ## PROTOCOL ALWAYS_CONSUMED
+
+[Depex]
+  gEfiAcpiTableProtocolGuid AND gEfiAcpiSdtProtocolGuid
+
diff --git a/Silicon/Hisilicon/Hi1620/Pptt/Pptt.h b/Silicon/Hisilicon/Hi1620/Pptt/Pptt.h
new file mode 100644
index 0000000000..5f2ec67cb9
--- /dev/null
+++ b/Silicon/Hisilicon/Hi1620/Pptt/Pptt.h
@@ -0,0 +1,68 @@ 
+/** @file
+*
+*  Copyright (c) 2018, Hisilicon Limited. All rights reserved.
+*  Copyright (c) 2018, Linaro Limited. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+*  Based on the files under Platform/ARM/JunoPkg/AcpiTables/
+*
+**/
+
+#ifndef _PPTT_H_
+#define _PPTT_H_
+
+#include <PlatformArch.h>
+#include <IndustryStandard/Acpi.h>
+#include <Library/ArmLib/ArmLibPrivate.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Protocol/AcpiSystemDescriptionTable.h>
+#include <Protocol/AcpiTable.h>
+
+#define PPTT_VENDOR_ID             SIGNATURE_32('H', 'I', 'S', 'I')
+
+#define EFI_ACPI_MAX_NUM_TABLES    20
+
+#define MAX_SCL_PER_SOCKET         MAX_DIE
+#define MAX_SCL                    (MAX_SOCKET * MAX_SCL_PER_SOCKET)
+#define MAX_CLUSTER_PER_SCL        8
+
+#define PPTT_TABLE_MAX_LEN         0x6000
+#define PPTT_SOCKET_COMPONENT_NO   0x1
+#define PPTT_CACHE_NO              0x4
+
+typedef union {
+  struct {
+    UINT32    InD           :1;
+    UINT32    Level         :3;
+    UINT32    Reserved      :28;
+  } Bits;
+  UINT32 Data;
+} CSSELR_DATA;
+
+typedef union {
+  struct {
+    UINT32    LineSize           :3;
+    UINT32    Associativity      :10;
+    UINT32    NumSets            :15;
+    UINT32    Wa                 :1;
+    UINT32    Ra                 :1;
+    UINT32    Wb                 :1;
+    UINT32    Wt                 :1;
+  } Bits;
+  UINT32 Data;
+} CCSIDR_DATA;
+
+#endif    // _PPTT_H_
+
diff --git a/Silicon/Hisilicon/Hi1620/Pptt/Pptt.c b/Silicon/Hisilicon/Hi1620/Pptt/Pptt.c
new file mode 100644
index 0000000000..944b4b9507
--- /dev/null
+++ b/Silicon/Hisilicon/Hi1620/Pptt/Pptt.c
@@ -0,0 +1,543 @@ 
+/** @file
+*
+*  Copyright (c) 2018, Hisilicon Limited. All rights reserved.
+*  Copyright (c) 2018, Linaro Limited. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+*  Based on the files under Platform/ARM/JunoPkg/AcpiTables/
+*
+**/
+
+#include "Pptt.h"
+
+typedef EFI_ACPI_5_1_GIC_STRUCTURE                          ACPI_GIC_STRUCTURE;
+typedef EFI_ACPI_5_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER ACPI_MADT_TABLE_HEADER;
+
+EFI_ACPI_TABLE_PROTOCOL       *mAcpiTableProtocol = NULL;
+EFI_ACPI_SDT_PROTOCOL         *mAcpiSdtProtocol   = NULL;
+
+EFI_ACPI_DESCRIPTION_HEADER mPpttHeader =
+  ARM_ACPI_HEADER (
+    EFI_ACPI_6_2_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_STRUCTURE_SIGNATURE,
+    EFI_ACPI_DESCRIPTION_HEADER,
+    EFI_ACPI_6_2_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_REVISION
+  );
+
+EFI_ACPI_6_2_PPTT_STRUCTURE_ID mPpttSocketType2[PPTT_SOCKET_COMPONENT_NO] =
+{
+  {2, sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_ID), {0, 0}, PPTT_VENDOR_ID, 0, 0, 0, 0, 0}
+};
+
+EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE mPpttCacheType1[PPTT_CACHE_NO];
+
+STATIC UINT32 mSocketOffset[MAX_SOCKET];
+STATIC UINT32 mScclOffset[MAX_SCL];
+STATIC UINT32 mClusterOffset[MAX_SCL][MAX_CLUSTER_PER_SCL];
+
+STATIC
+VOID
+InitCacheInfo (
+  VOID
+  )
+{
+  UINT8                                        Index;
+  EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE_ATTRIBUTES Type1Attributes;
+  CSSELR_DATA                                  CsselrData;
+  CCSIDR_DATA                                  CcsidrData;
+
+  for (Index = 0; Index < PPTT_CACHE_NO; Index++) {
+    CsselrData.Data = 0;
+    CcsidrData.Data = 0;
+    SetMem (
+      &Type1Attributes,
+      sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE_ATTRIBUTES),
+      0
+      );
+
+    if (Index == 0) { //L1I
+      CsselrData.Bits.InD = 1;
+      CsselrData.Bits.Level = 0;
+      Type1Attributes.CacheType  = 1;
+    } else if (Index == 1) {
+      Type1Attributes.CacheType  = 0;
+      CsselrData.Bits.Level = Index - 1;
+    } else {
+      Type1Attributes.CacheType  = 2;
+      CsselrData.Bits.Level = Index - 1;
+    }
+
+    CcsidrData.Data = ReadCCSIDR (CsselrData.Data);
+
+    if (CcsidrData.Bits.Wa == 1) {
+      Type1Attributes.AllocationType = EFI_ACPI_6_2_CACHE_ATTRIBUTES_ALLOCATION_WRITE;
+      if (CcsidrData.Bits.Ra == 1) {
+        Type1Attributes.AllocationType = EFI_ACPI_6_2_CACHE_ATTRIBUTES_ALLOCATION_READ_WRITE;
+      }
+    }
+
+    if (CcsidrData.Bits.Wt == 1) {
+      Type1Attributes.WritePolicy = 1;
+    }
+    DEBUG ((DEBUG_INFO,
+            "[Acpi PPTT] Level = %x!CcsidrData = %x!\n",
+            CsselrData.Bits.Level,
+            CcsidrData.Data));
+
+    mPpttCacheType1[Index].Type = EFI_ACPI_6_2_PPTT_TYPE_CACHE;
+    mPpttCacheType1[Index].Length = sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE);
+    mPpttCacheType1[Index].Reserved[0] = 0;
+    mPpttCacheType1[Index].Reserved[1] = 0;
+    mPpttCacheType1[Index].Flags.SizePropertyValid = 1;
+    mPpttCacheType1[Index].Flags.NumberOfSetsValid = 1;
+    mPpttCacheType1[Index].Flags.AssociativityValid = 1;
+    mPpttCacheType1[Index].Flags.AllocationTypeValid = 1;
+    mPpttCacheType1[Index].Flags.CacheTypeValid = 1;
+    mPpttCacheType1[Index].Flags.WritePolicyValid = 1;
+    mPpttCacheType1[Index].Flags.LineSizeValid = 1;
+    mPpttCacheType1[Index].Flags.Reserved = 0;
+    mPpttCacheType1[Index].NextLevelOfCache = 0;
+
+    if (Index != PPTT_CACHE_NO - 1) {
+      mPpttCacheType1[Index].NumberOfSets = (UINT16)CcsidrData.Bits.NumSets + 1;
+      mPpttCacheType1[Index].Associativity = (UINT16)CcsidrData.Bits.Associativity + 1;
+      mPpttCacheType1[Index].LineSize = (UINT16)( 1 << (CcsidrData.Bits.LineSize + 4));
+      mPpttCacheType1[Index].Size = mPpttCacheType1[Index].LineSize *      \
+                                    mPpttCacheType1[Index].Associativity * \
+                                    mPpttCacheType1[Index].NumberOfSets;
+      CopyMem (
+        &mPpttCacheType1[Index].Attributes,
+        &Type1Attributes,
+        sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE_ATTRIBUTES)
+        );
+    } else {
+      // L3 cache
+      mPpttCacheType1[Index].Size = 0x2000000;       // 32MB
+      mPpttCacheType1[Index].NumberOfSets = 0x800;
+      mPpttCacheType1[Index].Associativity = 0x0F;   // CacheAssociativity16Way
+      SetMem (
+        &mPpttCacheType1[Index].Attributes,
+        sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE_ATTRIBUTES),
+        0x0A
+        );
+      mPpttCacheType1[Index].LineSize = 0x80;        // 128byte
+    }
+  }
+}
+
+STATIC
+EFI_STATUS
+AddCoreTable (
+  IN     EFI_ACPI_DESCRIPTION_HEADER *PpttTable,
+  IN OUT UINT32                      *PpttTableLengthRemain,
+  IN     UINT32                      Parent,
+  IN     UINT32                      ResourceNo,
+  IN     UINT32                      ProcessorId
+  )
+{
+  EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR *PpttType0;
+  EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE     *PpttType1;
+  UINT32                                *PrivateResource;
+  UINT8                                 Index;
+  UINT32                                NextLevelCacheOffset;
+
+  if (*PpttTableLengthRemain <
+      (sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR) + ResourceNo * 4)) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  PpttType0 = (EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR *)((UINT8 *)PpttTable +
+                                                        PpttTable->Length);
+  PpttType0->Type = 0;
+  SetMem (&PpttType0->Flags, sizeof (PpttType0->Flags), 0);
+  PpttType0->Flags.AcpiProcessorIdValid = EFI_ACPI_6_2_PPTT_PROCESSOR_ID_VALID;
+  PpttType0->Parent= Parent;
+  PpttType0->AcpiProcessorId = ProcessorId;
+  PpttType0->NumberOfPrivateResources = ResourceNo;
+  PpttType0->Length = sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR) +
+                      ResourceNo * 4;
+
+  *PpttTableLengthRemain  -= (UINTN)PpttType0->Length;
+  PpttTable->Length += PpttType0->Length;
+  PrivateResource = (UINT32 *)((UINT8 *)PpttType0 +
+                               sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR));
+
+  // Add cache type structure
+  for (Index = 0; Index < ResourceNo; Index++, PrivateResource++) {
+    if (*PpttTableLengthRemain < sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE)) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    *PrivateResource = PpttTable->Length;
+    PpttType1 = (EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE *)((UINT8 *)PpttTable +
+                                                      PpttTable->Length);
+    gBS->CopyMem (
+           PpttType1,
+           &mPpttCacheType1[Index],
+           sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE)
+           );
+    *PpttTableLengthRemain -= PpttType1->Length;
+    PpttTable->Length += PpttType1->Length;
+  }
+
+  NextLevelCacheOffset = *(PrivateResource - 1);
+  PrivateResource = (UINT32 *)(PpttType0 + 1);
+  // Set the next level to L2 for L1I and L1D
+  PpttType1 = (EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE *)((UINT8 *) PpttTable + *PrivateResource++);
+  PpttType1->NextLevelOfCache = NextLevelCacheOffset;
+  PpttType1 = (EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE *)((UINT8 *) PpttTable + *PrivateResource++);
+  PpttType1->NextLevelOfCache = NextLevelCacheOffset;
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+AddClusterTable (
+  IN     EFI_ACPI_DESCRIPTION_HEADER *PpttTable,
+  IN OUT UINT32                      *PpttTableLengthRemain,
+  IN     UINT32                      Parent,
+  IN     UINT32                      ResourceNo
+  )
+{
+  EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR *PpttType0;
+
+  if ((*PpttTableLengthRemain) <
+      (sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR) + ResourceNo * 4)) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  PpttType0 = (EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR *)((UINT8 *)PpttTable +
+                                                        PpttTable->Length);
+  PpttType0->Type = 0;
+  SetMem (&PpttType0->Flags, sizeof (PpttType0->Flags), 0);
+  PpttType0->Parent= Parent;
+  PpttType0->NumberOfPrivateResources = ResourceNo;
+  PpttType0->Length = sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR) +
+                      ResourceNo * 4;
+
+  *PpttTableLengthRemain -= PpttType0->Length;
+  PpttTable->Length += PpttType0->Length;
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+AddScclTable (
+  IN     EFI_ACPI_DESCRIPTION_HEADER *PpttTable,
+  IN OUT UINT32                      *PpttTableLengthRemain,
+  IN     UINT32                      Parent,
+  IN     UINT32                      ResourceNo
+  )
+{
+  EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR *PpttType0;
+  EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE     *PpttType1;
+  UINT32                                *PrivateResource;
+
+  if (*PpttTableLengthRemain <
+      (sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR) + ResourceNo * 4)) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  PpttType0 = (EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR *)((UINT8 *)PpttTable +
+                                                        PpttTable->Length);
+  PpttType0->Type = 0;
+  SetMem (&PpttType0->Flags, sizeof (PpttType0->Flags), 0);
+  PpttType0->Parent= Parent;
+  PpttType0->NumberOfPrivateResources = ResourceNo;
+  PpttType0->Length = sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR) +
+                      ResourceNo * 4;
+
+  *PpttTableLengthRemain -= PpttType0->Length;
+  PpttTable->Length += PpttType0->Length;
+  PrivateResource = (UINT32 *)((UINT8 *)PpttType0 +
+                               sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR));
+
+  // Add cache type structure
+  if (*PpttTableLengthRemain < sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE)) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  *PrivateResource = PpttTable->Length;
+  PpttType1 = (EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE *)((UINT8 *)PpttTable +
+                                                    PpttTable->Length);
+  gBS->CopyMem (
+         PpttType1,
+         &mPpttCacheType1[3],
+         sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE)
+         );
+  *PpttTableLengthRemain -= PpttType1->Length;
+  PpttTable->Length += PpttType1->Length;
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+AddSocketTable (
+  IN     EFI_ACPI_DESCRIPTION_HEADER *PpttTable,
+  IN OUT UINT32                      *PpttTableLengthRemain,
+  IN     UINT32                      Parent,
+  IN     UINT32                      ResourceNo
+  )
+{
+  EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR *PpttType0;
+  EFI_ACPI_6_2_PPTT_STRUCTURE_ID        *PpttType2;
+  UINT32                                *PrivateResource;
+  UINT8                                 Index;
+
+  if (*PpttTableLengthRemain < sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR)) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  PpttType0 = (EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR *)((UINT8 *)PpttTable +
+                                                        PpttTable->Length);
+  PpttType0->Type = 0;
+  SetMem (&PpttType0->Flags, sizeof (PpttType0->Flags), 0);
+  PpttType0->Flags.PhysicalPackage = EFI_ACPI_6_2_PPTT_PROCESSOR_ID_VALID;
+  PpttType0->Parent= Parent;
+  PpttType0->NumberOfPrivateResources = ResourceNo;
+  PpttType0->Length = sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR) +
+                      ResourceNo * 4;
+  PpttTable->Length += PpttType0->Length;
+
+  *PpttTableLengthRemain -= PpttType0->Length;
+  if (*PpttTableLengthRemain < ResourceNo * 4) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  PrivateResource = (UINT32 *)((UINT8 *)PpttType0 +
+                               sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR));
+  DEBUG ((DEBUG_INFO,
+          "[Acpi PPTT]  sizeof(EFI_ACPI_6_2_PPTT_STRUCTURE_ID) = %x!\n",
+          sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_ID)));
+
+  for (Index = 0; Index < ResourceNo; Index++, PrivateResource++) {
+    if (*PpttTableLengthRemain < sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_ID)) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    *PrivateResource = PpttTable->Length;
+    PpttType2 = (EFI_ACPI_6_2_PPTT_STRUCTURE_ID *)((UINT8 *)PpttTable +
+                                                   PpttTable->Length);
+    gBS->CopyMem (
+           PpttType2,
+           &mPpttSocketType2[Index],
+           sizeof (EFI_ACPI_6_2_PPTT_STRUCTURE_ID)
+           );
+    *PpttTableLengthRemain -= PpttType2->Length;
+    PpttTable->Length += PpttType2->Length;
+  }
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+VOID
+GetAffLvl (
+  IN     UINT64     Mpidr,
+  IN OUT UINT8      *Level3,
+  IN OUT UINT8      *Level2,
+  IN OUT UINT8      *Level1,
+  IN OUT UINT8      *Level0
+  )
+{
+  *Level3 = BitFieldRead64 (Mpidr, 32, 39);
+  *Level2 = BitFieldRead64 (Mpidr, 16, 23);
+  *Level1 = BitFieldRead64 (Mpidr, 8, 15);
+  *Level0 = BitFieldRead64 (Mpidr, 0, 7);
+}
+
+
+STATIC
+VOID
+GetApic (
+  IN     ACPI_MADT_TABLE_HEADER                 *ApicTable,
+  IN OUT EFI_ACPI_DESCRIPTION_HEADER            *PpttTable,
+  IN     UINT32                                 PpttTableLengthRemain
+)
+{
+  UINT32                Parent = 0;
+  UINT32                ResourceNo = 0;
+  ACPI_GIC_STRUCTURE    *Ptr;
+  UINT8                 AffLvl3 = 0;
+  UINT8                 AffLvl2 = 0;
+  UINT8                 AffLvl1 = 0;
+  UINT8                 AffLvl0 = 0;
+  UINTN                 SocketIndex;
+
+  for (Ptr = (ACPI_GIC_STRUCTURE *) (ApicTable + 1);
+      (UINTN) Ptr < (UINTN) ApicTable + ApicTable->Header.Length;
+      Ptr = (ACPI_GIC_STRUCTURE *) ((UINTN) Ptr + Ptr->Length)) {
+
+    // Avoid dead loop due to corrupted MADT
+    if (Ptr->Length == 0) {
+      DEBUG ((DEBUG_ERROR, "[%a:%d] - Invalid MADT sub structure at 0x%x\n",
+            __FUNCTION__, __LINE__, (UINTN) Ptr - (UINTN) ApicTable));
+      break;
+    }
+
+    if (Ptr->Type != EFI_ACPI_5_1_GIC ||
+        (Ptr->Flags & EFI_ACPI_5_1_GIC_ENABLED) == 0) {
+      continue;
+    }
+    GetAffLvl (Ptr->MPIDR, &AffLvl3, &AffLvl2, &AffLvl1, &AffLvl0);
+    // AffLvl3 is not used for Hi1620
+    // And socket index is calculated by AffLvl2
+
+    SocketIndex = AffLvl2 / MAX_SCL_PER_SOCKET;
+    if (mSocketOffset[SocketIndex] == 0) {
+      //Add socket for type0 table
+      ResourceNo = PPTT_SOCKET_COMPONENT_NO;
+      mSocketOffset[SocketIndex] = PpttTable->Length;
+      Parent = 0;
+      AddSocketTable (
+        PpttTable,
+        &PpttTableLengthRemain,
+        Parent,
+        ResourceNo
+        );
+    }
+
+    if (mScclOffset[AffLvl2] == 0) {
+      //Add SCCL for type0 table
+      ResourceNo = 1;
+      mScclOffset[AffLvl2] = PpttTable->Length ;
+      Parent = mSocketOffset[SocketIndex];
+      AddScclTable (
+        PpttTable,
+        &PpttTableLengthRemain,
+        Parent,
+        ResourceNo
+        );
+    }
+
+    if (mClusterOffset[AffLvl2][AffLvl1] == 0) {
+      // Add cluster for type0 table
+      // No private resource for cluster on Hi1620
+      ResourceNo = 0;
+      mClusterOffset[AffLvl2][AffLvl1] = PpttTable->Length ;
+      Parent = mScclOffset[AffLvl2];
+      AddClusterTable (
+        PpttTable,
+        &PpttTableLengthRemain,
+        Parent,
+        ResourceNo
+        );
+    }
+
+    //Add core for type0 table
+    ResourceNo = 3;
+    Parent = mClusterOffset[AffLvl2][AffLvl1];
+    AddCoreTable (
+      PpttTable,
+      &PpttTableLengthRemain,
+      Parent,
+      ResourceNo,
+      Ptr->AcpiProcessorUid
+      );
+  }
+}
+
+
+STATIC
+VOID
+PpttSetAcpiTable(
+  IN EFI_EVENT    Event,
+  IN VOID         *Context
+  )
+{
+  UINTN                                         AcpiTableHandle;
+  EFI_STATUS                                    Status;
+  UINT8                                         Checksum;
+  EFI_ACPI_SDT_HEADER                           *Table;
+  ACPI_MADT_TABLE_HEADER                        *ApicTable;
+  EFI_ACPI_TABLE_VERSION                        TableVersion;
+  EFI_ACPI_DESCRIPTION_HEADER                   *PpttTable;
+  UINTN                                         TableKey;
+  UINT32                                        Index0;
+  UINT32                                        PpttTableLengthRemain = 0;
+
+  gBS->CloseEvent (Event);
+
+  InitCacheInfo ();
+
+  PpttTable = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (PPTT_TABLE_MAX_LEN);
+  gBS->CopyMem (
+         (VOID *)PpttTable,
+         &mPpttHeader,
+         sizeof (EFI_ACPI_DESCRIPTION_HEADER)
+         );
+  PpttTableLengthRemain = PPTT_TABLE_MAX_LEN - sizeof (EFI_ACPI_DESCRIPTION_HEADER);
+
+  for (Index0 = 0; Index0 < EFI_ACPI_MAX_NUM_TABLES; Index0++) {
+    Status = mAcpiSdtProtocol->GetAcpiTable (
+                                 Index0,
+                                 &Table,
+                                 &TableVersion,
+                                 &TableKey
+                                 );
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+
+    // Find APIC table
+    if (Table->Signature == EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE) {
+      break;
+    }
+
+  }
+
+  if (!EFI_ERROR (Status) && (Index0 != EFI_ACPI_MAX_NUM_TABLES)) {
+    ApicTable = (ACPI_MADT_TABLE_HEADER *)Table;
+
+    GetApic (ApicTable, PpttTable, PpttTableLengthRemain);
+
+    Checksum = CalculateCheckSum8 ((UINT8 *)(PpttTable), PpttTable->Length);
+    PpttTable->Checksum = Checksum;
+
+    AcpiTableHandle = 0;
+    Status = mAcpiTableProtocol->InstallAcpiTable (
+                                   mAcpiTableProtocol,
+                                   PpttTable,
+                                   PpttTable->Length,
+                                   &AcpiTableHandle);
+  }
+
+  FreePool (PpttTable);
+  return ;
+}
+
+EFI_STATUS
+EFIAPI
+PpttEntryPoint(
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS              Status;
+  EFI_EVENT               ReadyToBootEvent;
+
+  Status = gBS->LocateProtocol (
+                  &gEfiAcpiTableProtocolGuid,
+                  NULL,
+                  (VOID **)&mAcpiTableProtocol);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->LocateProtocol (
+                  &gEfiAcpiSdtProtocolGuid,
+                  NULL,
+                  (VOID **)&mAcpiSdtProtocol);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = EfiCreateEventReadyToBootEx (
+             TPL_NOTIFY,
+             PpttSetAcpiTable,
+             NULL,
+             &ReadyToBootEvent
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  DEBUG ((DEBUG_INFO, "Acpi Pptt init done.\n"));
+
+  return Status;
+}