[edk2-devel] [edk2-platforms][PATCH 09/34] JadePkg: Install some ACPI tables at runtime

Nhi Pham via groups.io nhi=os.amperecomputing.com at groups.io
Wed Dec 9 09:25:06 UTC 2020


This supports to create MADT, PPTT, PCCT, SLIT, SRAT, NFIT tables at
runtime. It also updates DSDT table based on the system information.

Signed-off-by: Nhi Pham <nhi at os.amperecomputing.com>
---
 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf |  22 ++
 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatform.h      |  48 +++
 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiDsdt.c          | 221 ++++++++++++
 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiMADT.c          | 372 ++++++++++++++++++++
 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiNfit.c          | 268 ++++++++++++++
 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPCCT.c          | 264 ++++++++++++++
 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPPTT.c          | 338 ++++++++++++++++++
 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c   |  84 +++++
 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSLIT.c          |  85 +++++
 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSRAT.c          | 268 ++++++++++++++
 10 files changed, 1970 insertions(+)

diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf
index 1ec8602aede5..d9caca9438de 100644
--- a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf
+++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf
@@ -15,6 +15,13 @@ [Defines]
   ENTRY_POINT                    = AcpiPlatformDxeInitialize
 
 [Sources.common]
+  AcpiDsdt.c
+  AcpiMADT.c
+  AcpiNfit.c
+  AcpiPCCT.c
+  AcpiPPTT.c
+  AcpiSLIT.c
+  AcpiSRAT.c
   AcpiPlatform.h
   AcpiPlatformDxe.c
 
@@ -35,10 +42,25 @@ [LibraryClasses]
   BaseLib
   UefiLib
   AcpiLib
+  AcpiPccLib
+  AcpiHelperLib
+  AmpereCpuLib
+
+[Pcd]
+  gArmPlatformTokenSpaceGuid.PcdCoreCount
+  gArmPlatformTokenSpaceGuid.PcdClusterCount
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision
+  gAmpereTokenSpaceGuid.PcdPmproDbBaseReg
+  gAmpereTokenSpaceGuid.PcdSmproDbBaseReg
 
 [Guids]
   gArmMpCoreInfoGuid
   gEfiAcpiTableGuid
+  gEfiEventReadyToBootGuid
 
 [Protocols]
   gEfiAcpiTableProtocolGuid                     ## ALWAYS_CONSUMED
diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatform.h b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatform.h
index 60b2ed22d05b..ba5d704a3fc0 100644
--- a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatform.h
+++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatform.h
@@ -22,5 +22,53 @@
 #include <Library/UefiRuntimeServicesTableLib.h>
 #include <Library/PrintLib.h>
 #include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+
+#include <Library/AcpiHelperLib.h>
+#include <Library/AmpereCpuLib.h>
+#include <Platform/Ac01.h>
+#include <PlatformInfoHob.h>
+#include <AcpiHeader.h>
+
+EFI_STATUS
+AcpiPatchDsdtTable (
+  VOID
+  );
+
+EFI_STATUS
+AcpiInstallMadtTable (
+  VOID
+  );
+
+EFI_STATUS
+AcpiInstallNfitTable (
+  VOID
+  );
+
+EFI_STATUS
+AcpiPcctInit (
+  VOID
+  );
+
+EFI_STATUS
+AcpiInstallPcctTable (
+  VOID
+  );
+
+EFI_STATUS
+AcpiInstallPpttTable (
+  VOID
+  );
+
+EFI_STATUS
+AcpiInstallSlitTable (
+  VOID
+  );
+
+EFI_STATUS
+AcpiInstallSratTable (
+  VOID
+  );
 
 #endif /* _ACPI_PLATFORM_H_ */
diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiDsdt.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiDsdt.c
new file mode 100755
index 000000000000..7d4501311a9f
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiDsdt.c
@@ -0,0 +1,221 @@
+/** @file
+
+  Copyright (c) 2020, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "AcpiPlatform.h"
+
+#define SUBNUMA_MODE_MONOLITHIC        0
+#define SUBNUMA_MODE_HEMISPHERE        1
+#define SUBNUMA_MODE_QUADRANT          2
+
+STATIC VOID
+AcpiPatchCmn600 (VOID)
+{
+  CHAR8     NodePath[MAX_ACPI_NODE_PATH];
+  UINTN     Index;
+
+  for (Index = 0; Index < GetNumberSupportedSockets (); Index++) {
+    AsciiSPrint (NodePath, sizeof (NodePath), "\\_SB.CMN%1X._STA", Index);
+    if (GetNumberActiveCPMsPerSocket (Index)) {
+      AcpiDSDTSetNodeStatusValue (NodePath, 0xf);
+    } else {
+      AcpiDSDTSetNodeStatusValue (NodePath, 0x0);
+    }
+  }
+}
+
+STATIC VOID
+AcpiPatchDmc620 (VOID)
+{
+  CHAR8                 NodePath[MAX_ACPI_NODE_PATH];
+  UINTN                 Index, Index1;
+  EFI_GUID              PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2;
+  PlatformInfoHob_V2    *PlatformHob;
+  UINT32                McuMask;
+  VOID                  *Hob;
+
+  Hob = GetFirstGuidHob (&PlatformHobGuid);
+  if (Hob == NULL) {
+    return;
+  }
+
+  PlatformHob = (PlatformInfoHob_V2 *) GET_GUID_HOB_DATA (Hob);
+
+  for (Index = 0; Index < GetNumberSupportedSockets (); Index++) {
+    McuMask = PlatformHob->DramInfo.McuMask[Index];
+    for (Index1 = 0; Index1 < sizeof (McuMask) * 8; Index1++) {
+      AsciiSPrint (NodePath, sizeof (NodePath), "\\_SB.MC%1X%1X._STA", Index, Index1);
+      if (McuMask & (0x1 << Index1)) {
+        AcpiDSDTSetNodeStatusValue (NodePath, 0xf);
+      } else {
+        AcpiDSDTSetNodeStatusValue (NodePath, 0x0);
+      }
+    }
+  }
+}
+
+STATIC VOID
+AcpiPatchNvdimm (VOID)
+{
+  CHAR8                 NodePath[MAX_ACPI_NODE_PATH];
+  UINTN                 NvdRegionNum, Count;
+  EFI_GUID              PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2;
+  PlatformInfoHob_V2    *PlatformHob;
+  VOID                  *Hob;
+
+  Hob = GetFirstGuidHob (&PlatformHobGuid);
+  if (Hob == NULL) {
+    return;
+  }
+
+  PlatformHob = (PlatformInfoHob_V2 *) GET_GUID_HOB_DATA (Hob);
+
+  NvdRegionNum = 0;
+  for (Count = 0; Count < PlatformHob->DramInfo.NumRegion; Count++) {
+    if (PlatformHob->DramInfo.NvdRegion[Count]) {
+      NvdRegionNum += 1;
+    }
+  }
+
+  if (NvdRegionNum == PLATFORM_MAX_NUM_NVDIMM_DEVICE) {
+    return;
+  }
+
+  /* Disable NVDIMM Root Device */
+  if (NvdRegionNum == 0) {
+    AsciiSPrint (NodePath, sizeof (NodePath), "\\_SB.NVDR._STA");
+    AcpiDSDTSetNodeStatusValue (NodePath, 0x0);
+  }
+
+  /* Disable NVDIMM Device which is not available */
+  Count = NvdRegionNum + 1;
+  while (Count <= PLATFORM_MAX_NUM_NVDIMM_DEVICE) {
+    AsciiSPrint (NodePath, sizeof (NodePath), "\\_SB.NVDR.NVD%1X._STA", Count);
+    AcpiDSDTSetNodeStatusValue (NodePath, 0x0);
+    Count++;
+  }
+}
+
+STATIC VOID
+AcpiPatchHwmon (VOID)
+{
+  CHAR8     NodePath[MAX_ACPI_NODE_PATH];
+  UINTN     Index;
+
+  // PCC Hardware Monitor Devices
+  for (Index = 0; Index < GetNumberSupportedSockets (); Index++) {
+    AsciiSPrint (NodePath, sizeof (NodePath), "\\_SB.HM0%1X._STA", Index);
+    if (GetNumberActiveCPMsPerSocket (Index)) {
+      AcpiDSDTSetNodeStatusValue (NodePath, 0xf);
+    } else {
+      AcpiDSDTSetNodeStatusValue (NodePath, 0x0);
+    }
+  }
+
+  // Ampere Altra SoC Hardware Monitor Devices
+  for (Index = 0; Index < GetNumberSupportedSockets (); Index++) {
+    AsciiSPrint (NodePath, sizeof (NodePath), "\\_SB.HM0%1X._STA", Index + 2);
+    if (GetNumberActiveCPMsPerSocket (Index)) {
+      AcpiDSDTSetNodeStatusValue (NodePath, 0xf);
+    } else {
+      AcpiDSDTSetNodeStatusValue (NodePath, 0x0);
+    }
+  }
+}
+
+STATIC VOID
+AcpiPatchDsu (VOID)
+{
+  CHAR8                 NodePath[MAX_ACPI_NODE_PATH];
+  UINTN                 Index;
+
+  for (Index = 0; Index < PLATFORM_CPU_MAX_NUM_CORES; Index += PLATFORM_CPU_NUM_CORES_PER_CPM) {
+    AsciiSPrint (NodePath, sizeof(NodePath), "\\_SB.DU%2X._STA", Index / PLATFORM_CPU_NUM_CORES_PER_CPM);
+    if (IsCpuEnabled (Index)) {
+      AcpiDSDTSetNodeStatusValue (NodePath, 0xf);
+    } else {
+      AcpiDSDTSetNodeStatusValue (NodePath, 0x0);
+    }
+  }
+}
+
+STATIC UINT8
+PcieGetSubNumaMode (
+  VOID
+  )
+{
+  EFI_GUID                    PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2;
+  PlatformInfoHob_V2          *PlatformHob;
+  VOID                        *Hob;
+
+  /* Get the Platform HOB */
+  Hob = GetFirstGuidHob (&PlatformHobGuid);
+  if (Hob == NULL) {
+    return SUBNUMA_MODE_MONOLITHIC;
+  }
+  PlatformHob = (PlatformInfoHob_V2 *) GET_GUID_HOB_DATA (Hob);
+
+  return PlatformHob->SubNumaMode[0];
+}
+
+VOID
+AcpiPatchPcieNuma (
+  VOID
+  )
+{
+  CHAR8     NodePath[MAX_ACPI_NODE_PATH];
+  UINTN     Index;
+  UINTN     NumaIdx;
+  UINTN     NumPciePort;
+  UINTN     NumaAssignment[3][16] = {
+              { 0, 0, 0, 0, 0, 0, 0, 0,   // Monolitic Node 0 (S0)
+                1, 1, 1, 1, 1, 1, 1, 1 }, // Monolitic Node 1 (S1)
+              { 0, 1, 0, 1, 0, 0, 1, 1,   // Hemisphere Node 0, 1 (S0)
+                2, 3, 2, 3, 2, 2, 3, 3 }, // Hemisphere Node 2, 3 (S1)
+              { 0, 2, 1, 3, 1, 1, 3, 3,   // Quadrant Node 0, 1, 2, 3 (S0)
+                4, 6, 5, 7, 5, 5, 7, 7 }, // Quadrant Node 4, 5, 6, 7 (S1)
+              };
+
+  switch (PcieGetSubNumaMode ()) {
+  case SUBNUMA_MODE_MONOLITHIC:
+    NumaIdx = 0;
+    break;
+  case SUBNUMA_MODE_HEMISPHERE:
+    NumaIdx = 1;
+    break;
+  case SUBNUMA_MODE_QUADRANT:
+    NumaIdx = 2;
+    break;
+  default:
+    NumaIdx = 0;
+    break;
+  }
+
+  if (GetNumberActiveSockets () > 1) {
+    NumPciePort = 16; // 16 ports total (8 per socket)
+  } else {
+    NumPciePort = 8;  // 8 ports total
+  }
+
+  for (Index = 0; Index < NumPciePort; Index++) {
+    AsciiSPrint (NodePath, sizeof (NodePath), "\\_SB.PCI%X._PXM", Index);
+    AcpiDSDTSetNodeStatusValue (NodePath, NumaAssignment[NumaIdx][Index]);
+  }
+}
+
+EFI_STATUS
+AcpiPatchDsdtTable (VOID)
+{
+  AcpiPatchCmn600 ();
+  AcpiPatchDmc620 ();
+  AcpiPatchDsu ();
+  AcpiPatchHwmon ();
+  AcpiPatchNvdimm ();
+  AcpiPatchPcieNuma ();
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiMADT.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiMADT.c
new file mode 100755
index 000000000000..fc34801fa340
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiMADT.c
@@ -0,0 +1,372 @@
+/** @file
+
+  Copyright (c) 2020, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "AcpiPlatform.h"
+
+EFI_ACPI_6_3_GIC_ITS_STRUCTURE GicItsTemplate = {
+  EFI_ACPI_6_3_GIC_ITS,
+  sizeof (EFI_ACPI_6_3_GIC_ITS_STRUCTURE),
+  EFI_ACPI_RESERVED_WORD,
+  0, /* GicItsId */
+  0, /* PhysicalBaseAddress */
+  0, /* Reserved2 */
+};
+
+EFI_ACPI_6_3_GICR_STRUCTURE GicRTemplate = {
+  EFI_ACPI_6_3_GICR,
+  sizeof (EFI_ACPI_6_3_GICR_STRUCTURE),
+  EFI_ACPI_RESERVED_WORD,
+  GICR_MASTER_BASE_REG, /* DiscoveryRangeBaseAddress */
+  0x1000000, /* DiscoveryRangeLength */
+};
+
+EFI_ACPI_6_3_GIC_DISTRIBUTOR_STRUCTURE GicDTemplate = {
+  EFI_ACPI_6_3_GICD,
+  sizeof (EFI_ACPI_6_3_GIC_DISTRIBUTOR_STRUCTURE),
+  EFI_ACPI_RESERVED_WORD,
+  0, /* GicDistHwId */
+  GICD_BASE_REG, /* GicDistBase */
+  0, /* GicDistVector */
+  0x3, /* GicVersion */
+  {EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE}
+};
+
+EFI_ACPI_6_3_GIC_STRUCTURE GiccTemplate = {
+  EFI_ACPI_6_3_GIC,
+  sizeof (EFI_ACPI_6_3_GIC_STRUCTURE),
+  EFI_ACPI_RESERVED_WORD,
+  0, /* GicId */
+  0, /* AcpiCpuUid */
+  0, /* Flags */
+  0,
+  23, /* PmuIrq */
+  0,
+  0,
+  0,
+  0,
+  25, /* GsivId */
+  0, /* GicRBase */
+  0, /* Mpidr */
+  0, /* ProcessorPowerEfficiencyClass */
+  0, /* Reserved2 */
+  21, /* SPE irq */
+};
+
+EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER MADTTableHeaderTemplate = {
+  __ACPI_HEADER (
+    EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
+    0, /* need fill in */
+    EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
+  ),
+};
+
+UINT32 Ac01CoreOrderMonolithic[PLATFORM_CPU_MAX_CPM * PLATFORM_CPU_NUM_CORES_PER_CPM] = {
+  36, 52, 40, 56, 32, 48, 44, 60,
+  20, 68, 24, 72, 16, 64, 28, 76,
+  4, 8, 0, 12, 38, 54, 42, 58,
+  34, 50, 46, 62, 22, 70, 26, 74,
+  18, 66, 30, 78, 6, 10, 2, 14,
+  37, 53, 41, 57, 33, 49, 45, 61,
+  21, 69, 25, 73, 17, 65, 29, 77,
+  5, 9, 1, 13, 39, 55, 43, 59,
+  35, 51, 47, 63, 23, 71, 27, 75,
+  19, 67, 31, 79, 7, 11, 3, 15,
+};
+
+UINT32 Ac01CoreOrderHemisphere[PLATFORM_CPU_MAX_CPM * PLATFORM_CPU_NUM_CORES_PER_CPM] = {
+  32, 48, 16, 64, 36, 52, 0, 20,
+  68, 4, 34, 50, 18, 66, 38, 54,
+  2, 22, 70, 6, 33, 49, 17, 65,
+  37, 53, 1, 21, 69, 5, 35, 51,
+  19, 67, 39, 55, 3, 23, 71, 7,
+  44, 60, 28, 76, 40, 56, 12, 24,
+  72, 8, 46, 62, 30, 78, 42, 58,
+  14, 26, 74, 10, 45, 61, 29, 77,
+  41, 57, 13, 25, 73, 9, 47, 63,
+  31, 79, 43, 59, 15, 27, 75, 11,
+};
+
+UINT32 Ac01CoreOrderQuadrant[PLATFORM_CPU_MAX_CPM * PLATFORM_CPU_NUM_CORES_PER_CPM] = {
+  16, 32, 0, 20, 4, 18, 34, 2,
+  22, 6, 17, 33, 1, 21, 5, 19,
+  35, 3, 23, 7, 48, 64, 52, 68,
+  36, 50, 66, 54, 70, 38, 49, 65,
+  53, 69, 37, 51, 67, 55, 71, 39,
+  28, 44, 12, 24, 8, 30, 46, 14,
+  26, 10, 29, 45, 13, 25, 9, 31,
+  47, 15, 27, 11, 60, 76, 56, 72,
+  40, 62, 78, 58, 74, 42, 61, 77,
+  57, 73, 41, 63, 79, 59, 75, 43,
+};
+
+EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *MadtTablePointer;
+
+STATIC UINT32 *
+CPUGetCoreOrder (VOID)
+{
+  EFI_GUID                    PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2;
+  PlatformInfoHob_V2          *PlatformHob;
+  VOID                        *Hob;
+  UINT32                      SubNumaMode;
+  UINT8                       Ac01Chip = 1;
+
+  /* Get the Platform HOB */
+  Hob = GetFirstGuidHob (&PlatformHobGuid);
+  if (Hob == NULL) {
+    return SUBNUMA_MODE_MONOLITHIC;
+  }
+  PlatformHob = (PlatformInfoHob_V2 *) GET_GUID_HOB_DATA (Hob);
+  Ac01Chip = ((PlatformHob->ScuProductId[0] & 0xFF) == 0x1) ? 1 : 0;
+
+  SubNumaMode = CPUGetSubNumaMode();
+  switch (SubNumaMode) {
+  case SUBNUMA_MODE_MONOLITHIC:
+    if (Ac01Chip != 0) {
+      return (UINT32 *) &Ac01CoreOrderMonolithic;
+    }
+  case SUBNUMA_MODE_HEMISPHERE:
+    if (Ac01Chip != 0) {
+      return (UINT32 *) &Ac01CoreOrderHemisphere;
+    }
+    return (UINT32 *) &Ac01CoreOrderHemisphere;
+  case SUBNUMA_MODE_QUADRANT:
+    if (Ac01Chip != 0) {
+      return (UINT32 *) &Ac01CoreOrderQuadrant;
+    }
+  }
+
+  if (Ac01Chip != 0) {
+    return (UINT32 *) &Ac01CoreOrderMonolithic;
+  }
+
+  return NULL;
+}
+
+STATIC UINT32
+AcpiInstallMadtProcessorNode (
+  VOID *EntryPointer,
+  UINT32 CpuId
+  )
+{
+  EFI_ACPI_6_3_GIC_STRUCTURE   *MadtProcessorEntryPointer = EntryPointer;
+  UINT32                        SocketId;
+  UINT32                        ClusterId;
+  UINTN                         Size;
+
+  Size = sizeof (GiccTemplate);
+  CopyMem (MadtProcessorEntryPointer, &GiccTemplate, Size);
+
+  SocketId = CpuId / (PLATFORM_CPU_MAX_CPM * PLATFORM_CPU_NUM_CORES_PER_CPM);
+  ClusterId = CpuId / PLATFORM_CPU_NUM_CORES_PER_CPM;
+  if (SocketId == 1) {
+    ClusterId -= PLATFORM_CPU_MAX_CPM;
+  }
+
+  MadtProcessorEntryPointer->CPUInterfaceNumber = CpuId;
+  MadtProcessorEntryPointer->AcpiProcessorUid =
+    (SocketId << PLATFORM_SOCKET_UID_BIT_OFFSET) +
+    (ClusterId << 8) + (CpuId  % PLATFORM_CPU_NUM_CORES_PER_CPM);
+  MadtProcessorEntryPointer->Flags = 1;
+  MadtProcessorEntryPointer->MPIDR =
+    (((ClusterId << 8) + (CpuId  % PLATFORM_CPU_NUM_CORES_PER_CPM)) << 8) ;
+  MadtProcessorEntryPointer->MPIDR += (((UINT64) SocketId) << 32);
+
+  return Size;
+}
+
+STATIC UINT32
+AcpiInstallMadtGicD (
+  VOID *EntryPointer
+  )
+{
+  EFI_ACPI_6_3_GIC_DISTRIBUTOR_STRUCTURE *GicDEntryPointer = EntryPointer;
+  UINTN Size;
+
+  Size = sizeof (GicDTemplate);
+  CopyMem (GicDEntryPointer, &GicDTemplate, Size);
+
+  return Size;
+}
+
+STATIC UINT32
+AcpiInstallMadtGicR (
+  VOID *EntryPointer,
+  UINT32 SocketId
+  )
+{
+  EFI_ACPI_6_3_GICR_STRUCTURE   *GicREntryPointer = EntryPointer;
+  UINTN                         Size;
+
+  /*
+   * If the Slave socket is not present, discard the Slave socket
+   * GIC redistributor region
+   */
+  if ((SocketId == 1) && (GetNumberActiveCPMsPerSocket (SocketId) == 0)) {
+    return 0;
+  }
+
+  Size = sizeof (GicRTemplate);
+  CopyMem (GicREntryPointer, &GicRTemplate, Size);
+
+  if (SocketId == 1) {
+    GicREntryPointer->DiscoveryRangeBaseAddress = GICR_SLAVE_BASE_REG;
+  }
+
+  return Size;
+}
+
+STATIC UINT32
+AcpiInstallMadtGicIts (
+  VOID *EntryPointer,
+  UINT32 Index
+  )
+{
+  EFI_ACPI_6_3_GIC_ITS_STRUCTURE *GicItsEntryPointer = EntryPointer;
+  UINTN                          Size, Offset;
+  UINT64                         GicBase = GICD_BASE_REG;
+  UINT32                         ItsId = Index;
+
+  if (Index > SOCKET0_LAST_RC) { /* Socket 1, Index: 8-15 */
+    GicBase = GICD_SLAVE_BASE_REG;
+    Index -= (SOCKET0_LAST_RC + 1); /* Socket 1, Index:8 -> RCA0 */
+  }
+  Size = sizeof(GicItsTemplate);
+  CopyMem (GicItsEntryPointer, &GicItsTemplate, Size);
+  Offset = 0x40000 + Index * 0x20000;
+  GicItsEntryPointer->GicItsId = ItsId;
+  GicItsEntryPointer->PhysicalBaseAddress = Offset + GicBase;
+
+  return Size;
+}
+
+/*
+ *  Install MADT table.
+ */
+EFI_STATUS
+AcpiInstallMadtTable (VOID)
+{
+  EFI_ACPI_6_3_GIC_STRUCTURE    *GiccEntryPointer = NULL;
+  EFI_ACPI_TABLE_PROTOCOL       *AcpiTableProtocol;
+  UINTN                         MadtTableKey  = 0;
+  INTN                          Count, Index;
+  EFI_STATUS                    Status;
+  UINTN                         Size;
+  UINT32                        *CoreOrder;
+  UINT32                        SktMaxCoreNum;
+
+  if (IsAcpiInstalled (EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE)) {
+    DEBUG ((DEBUG_INFO, "APIC table is already installed.  Skipping...\n"));
+    return EFI_ABORTED;
+  }
+
+  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid,
+                  NULL, (VOID **) &AcpiTableProtocol);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  for (Count = 0; Count < gST->NumberOfTableEntries; Count++) {
+    if (CompareGuid (&gArmMpCoreInfoGuid, &(gST->ConfigurationTable[Count].VendorGuid))) {
+      Size = sizeof(MADTTableHeaderTemplate) +
+             (PLATFORM_CPU_MAX_NUM_CORES * sizeof (GiccTemplate)) +
+             sizeof (GicDTemplate) +
+             (PLATFORM_CPU_MAX_SOCKET * sizeof (GicRTemplate)) +
+             ((SOCKET0_LAST_RC - SOCKET0_FIRST_RC +  1) * sizeof (GicItsTemplate));
+      if (GetNumberActiveSockets () > 1) {
+        Size += ((SOCKET1_LAST_RC - SOCKET1_FIRST_RC +  1) * sizeof (GicItsTemplate));
+      } else if (!PlatSlaveSocketPresent ()) {
+        Size += 2 * sizeof(GicItsTemplate); /* RCA0/1 */
+      }
+
+      MadtTablePointer =
+        (EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *) AllocateZeroPool(Size);
+      if (MadtTablePointer == NULL) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      GiccEntryPointer =
+          (EFI_ACPI_6_3_GIC_STRUCTURE *) ((UINT64) MadtTablePointer +
+          sizeof (MADTTableHeaderTemplate));
+
+      /* Install Gic interface for each processor */
+      Size = 0;
+      CoreOrder = CPUGetCoreOrder ();
+      ASSERT (CoreOrder != NULL);
+      SktMaxCoreNum = PLATFORM_CPU_MAX_CPM * PLATFORM_CPU_NUM_CORES_PER_CPM;
+      for (Index = 0; Index < SktMaxCoreNum; Index++) {
+        if (IsCpuEnabled (CoreOrder[Index])) {
+          Size += AcpiInstallMadtProcessorNode ((VOID *) ((UINT64) GiccEntryPointer + Size), CoreOrder[Index]);
+        }
+      }
+
+      for (Index = 0; Index < SktMaxCoreNum; Index++) {
+        if (IsCpuEnabled (CoreOrder[Index] + SktMaxCoreNum)) {
+          Size += AcpiInstallMadtProcessorNode ((VOID *) ((UINT64) GiccEntryPointer + Size), CoreOrder[Index] + SktMaxCoreNum);
+        }
+      }
+
+      /* Install Gic Distributor */
+      Size += AcpiInstallMadtGicD ((VOID *) ((UINT64) GiccEntryPointer + Size));
+
+      /* Install Gic Redistributor */
+      for (Index = 0; Index < PLATFORM_CPU_MAX_SOCKET; Index++) {
+        Size += AcpiInstallMadtGicR ((VOID *) ((UINT64) GiccEntryPointer + Size), Index);
+      }
+
+      /* Install Gic ITS */
+      if (!PlatSlaveSocketPresent ()) {
+        for (Index = 0; Index <= 1; Index++) { /* RCA0/1 */
+          Size += AcpiInstallMadtGicIts ((VOID *) ((UINT64) GiccEntryPointer + Size), Index);
+        }
+      }
+      for (Index = SOCKET0_FIRST_RC; Index <= SOCKET0_LAST_RC; Index++) {
+        Size += AcpiInstallMadtGicIts ((VOID *) ((UINT64) GiccEntryPointer + Size), Index);
+      }
+      if (GetNumberActiveSockets () > 1) {
+        for (Index = SOCKET1_FIRST_RC; Index <= SOCKET1_LAST_RC; Index++) {
+          Size += AcpiInstallMadtGicIts ((VOID *) ((UINT64) GiccEntryPointer + Size), Index);
+        }
+      }
+      CopyMem (MadtTablePointer, &MADTTableHeaderTemplate,
+              sizeof (MADTTableHeaderTemplate));
+
+      Size += sizeof (MADTTableHeaderTemplate);
+      MadtTablePointer->Header.Length = Size;
+      CopyMem (
+        MadtTablePointer->Header.OemId,
+        PcdGetPtr (PcdAcpiDefaultOemId),
+        sizeof (MadtTablePointer->Header.OemId)
+        );
+      MadtTablePointer->Header.OemTableId = EFI_ACPI_OEM_TABLE_ID;
+      MadtTablePointer->Header.OemRevision = 3;
+      MadtTablePointer->Header.CreatorId = EFI_ACPI_CREATOR_ID;
+      MadtTablePointer->Header.CreatorRevision = EFI_ACPI_CREATOR_REVISION;
+
+      AcpiTableChecksum ((UINT8 *) MadtTablePointer,
+                        MadtTablePointer->Header.Length);
+
+      Status = AcpiTableProtocol->InstallAcpiTable (
+                                    AcpiTableProtocol,
+                                    (VOID *) MadtTablePointer,
+                                    MadtTablePointer->Header.Length,
+                                    &MadtTableKey
+                                    );
+      FreePool ((VOID *) MadtTablePointer);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+      break;
+    }
+  }
+
+  if (Count == gST->NumberOfTableEntries) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiNfit.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiNfit.c
new file mode 100644
index 000000000000..fb22deef0aec
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiNfit.c
@@ -0,0 +1,268 @@
+/** @file
+
+  Copyright (c) 2020, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "AcpiPlatform.h"
+
+EFI_ACPI_6_3_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE NfitSPATemplate = {
+  EFI_ACPI_6_3_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE_TYPE,
+  sizeof (EFI_ACPI_6_3_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE),
+  0, // The uniue index - need to be filled.
+  0, // The flags - need to be filled.
+  0, // Reserved.
+  0, // Proximity domain - need to be filled.
+  EFI_ACPI_6_3_NFIT_GUID_BYTE_ADDRESSABLE_PERSISTENT_MEMORY_REGION, // PM range type.
+  0, // Start address - need to be filled.
+  0, // Size - need to be filled.
+  EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB | EFI_MEMORY_WP | EFI_MEMORY_UCE, // attribute - need to be filled.
+};
+
+EFI_ACPI_6_3_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE NvdimmControlRegionTemplate = {
+  EFI_ACPI_6_3_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE_TYPE,
+  sizeof (EFI_ACPI_6_3_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE),
+  0, // The unique index - need to be filled.
+  0x1122, // The vendor id - dummy value.
+  0x3344, // The device id - dummy value.
+  0, // The revision - dummy value.
+  0x5566, // The subsystem nvdimm id - dummy value.
+  0x7788, // The subsystem nvdimm device id - dummy value.
+  0x0, // The subsystem revision - dummy value.
+  0, // The valid field.
+  0, // The manufacturing location - not valid.
+  0, // The manufacturing date - not valid.
+  {0}, // Reserved.
+  0xaabbccdd, // The serial number - dummy value.
+  0, // The region format interface code - dummy value.
+  0, // The number of block control windows.
+  0, // The size of block control windows.
+  0, // The Command Register Offset in Block Control Window.
+  0, // The Size of Command Register in Block Control Windows.
+  0, // The Status Register Offset in Block Control Window.
+  0, // Size of Status Register in Block Control Windows.
+  0, // The NVDIMM Control Region Flag.
+  {0}, // Reserved.
+};
+
+EFI_ACPI_6_3_NFIT_NVDIMM_REGION_MAPPING_STRUCTURE NvdimmRegionMappingTemplate = {
+  EFI_ACPI_6_3_NFIT_NVDIMM_REGION_MAPPING_STRUCTURE_TYPE,
+  sizeof (EFI_ACPI_6_3_NFIT_NVDIMM_REGION_MAPPING_STRUCTURE),
+  {0}, // _ADR of the NVDIMM device - need to be filled.
+  0, // Dimm smbios handle index - need to be filled.
+  0, // The unique region index - need to be filled.
+  0, // The SPA range index - need to be filled.
+  0, // The control region index - need to be filled.
+  0, // The region size - need to be filled.
+  0, // The region offset - need to be filled.
+  0, // The region base - need to be filled.
+  0, // The interleave structure index - need to be filled.
+  0, // The interleave ways - need to be filled.
+  0, // NVDIMM flags - need to be filled.
+  0, // Reserved.
+};
+
+EFI_ACPI_6_3_NVDIMM_FIRMWARE_INTERFACE_TABLE NFITTableHeaderTemplate = {
+  __ACPI_HEADER (
+    EFI_ACPI_6_3_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE,
+    0, /* need fill in */
+    EFI_ACPI_6_3_NVDIMM_FIRMWARE_INTERFACE_TABLE_REVISION
+  ),
+  0x00000000, // Reserved
+};
+
+/*
+ * Count NVDIMM Region
+ */
+EFI_STATUS
+AcpiGetNvdRegionNumber (
+  IN OUT UINTN *NvdRegionNum
+  )
+{
+  CONST EFI_GUID      PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2;
+  PlatformInfoHob_V2  *PlatformHob;
+  UINTN               Count;
+  VOID                *Hob;
+
+  /* Get the Platform HOB */
+  Hob = GetFirstGuidHob (&PlatformHobGuid);
+  if (Hob == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  PlatformHob = (PlatformInfoHob_V2 *) GET_GUID_HOB_DATA (Hob);
+
+  *NvdRegionNum = 0;
+  for (Count = 0; Count < PlatformHob->DramInfo.NumRegion; Count++) {
+    if (PlatformHob->DramInfo.NvdRegion[Count]) {
+      *NvdRegionNum += 1;
+    }
+  }
+
+  if (*NvdRegionNum == 0) {
+    DEBUG ((DEBUG_INFO, "No NVDIMM Region\n"));
+    return EFI_INVALID_PARAMETER; /* No NVDIMM Region */
+  }
+
+  return EFI_SUCCESS;
+}
+
+/*
+ * Fill in SPA strucutre
+ */
+VOID
+AcpiNfitFillSPA (
+  IN OUT EFI_ACPI_6_3_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE *NfitSpaPointer,
+  IN     UINTN  NvdRegionIndex,
+  IN     UINT64 NvdRegionBase,
+  IN     UINT64 NvdRegionSize
+  )
+{
+  NfitSpaPointer->Flags                            = 0;
+  NfitSpaPointer->SPARangeStructureIndex           = NvdRegionIndex;
+  NfitSpaPointer->SystemPhysicalAddressRangeBase   = NvdRegionBase;
+  NfitSpaPointer->SystemPhysicalAddressRangeLength = NvdRegionSize;
+}
+
+VOID
+NfitFillControlRegion (
+  IN OUT EFI_ACPI_6_3_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE *NfitControlRegionPointer,
+  IN UINTN NvdRegionIndex
+  )
+{
+  NfitControlRegionPointer->NVDIMMControlRegionStructureIndex = NvdRegionIndex;
+}
+
+VOID
+NfitFillRegionMapping (
+  IN OUT EFI_ACPI_6_3_NFIT_NVDIMM_REGION_MAPPING_STRUCTURE *NfitRegionMappingPointer,
+  IN EFI_ACPI_6_3_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE *NfitControlRegionPointer,
+  IN EFI_ACPI_6_3_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE *NfitSpaPointer
+  )
+{
+  NfitRegionMappingPointer->NVDIMMControlRegionStructureIndex    = NfitControlRegionPointer->NVDIMMControlRegionStructureIndex;
+  NfitRegionMappingPointer->SPARangeStructureIndex               = NfitSpaPointer->SPARangeStructureIndex;
+  NfitRegionMappingPointer->NVDIMMPhysicalAddressRegionBase      = NfitSpaPointer->SystemPhysicalAddressRangeBase;
+  NfitRegionMappingPointer->NVDIMMRegionSize                     = NfitSpaPointer->SystemPhysicalAddressRangeLength;
+  NfitRegionMappingPointer->NFITDeviceHandle.DIMMNumber          = 1; // Hardcoded for now.
+  NfitRegionMappingPointer->NFITDeviceHandle.MemoryChannelNumber = 0; // Hardcoded for now.
+  NfitRegionMappingPointer->NFITDeviceHandle.MemoryControllerID  = 0; // Hardcoded for now.
+  NfitRegionMappingPointer->NFITDeviceHandle.NodeControllerID    = 0; // Hardcoded for now.
+  NfitRegionMappingPointer->NFITDeviceHandle.SocketID            = 0; // Hardcoded for now.
+  NfitRegionMappingPointer->RegionOffset                         = 0; // Hardcoded for now.
+}
+
+EFI_STATUS
+AcpiNfitFillTable (
+  IN EFI_ACPI_6_3_NVDIMM_FIRMWARE_INTERFACE_TABLE *NfitTablePointer
+  )
+{
+  EFI_ACPI_6_3_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE   *NfitSpaPointer;
+  EFI_ACPI_6_3_NFIT_NVDIMM_REGION_MAPPING_STRUCTURE           *NfitRegionMappingPointer;
+  EFI_ACPI_6_3_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE           *NfitControlRegionPointer;
+  CONST EFI_GUID PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2;
+  PlatformInfoHob_V2  *PlatformHob;
+  UINTN               Count;
+  VOID                *Hob;
+  UINTN               NvdRegionIndex;
+  UINT64              NvdRegionBase;
+  UINT64              NvdRegionSize;
+
+  /* Get the Platform HOB */
+  Hob = GetFirstGuidHob (&PlatformHobGuid);
+  if (Hob == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  PlatformHob = (PlatformInfoHob_V2 *) GET_GUID_HOB_DATA (Hob);
+
+  NfitSpaPointer = (EFI_ACPI_6_3_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE *)
+                   (NfitTablePointer + 1);
+  NvdRegionIndex = 0;
+  for (Count = 0; Count < PlatformHob->DramInfo.NumRegion; Count++) {
+    if (PlatformHob->DramInfo.NvdRegion[Count] != 0) {
+      NvdRegionIndex++;
+      NvdRegionBase = PlatformHob->DramInfo.Base[Count];
+      NvdRegionSize = PlatformHob->DramInfo.Size[Count];
+
+      CopyMem ((VOID *) NfitSpaPointer, (VOID *) &NfitSPATemplate, sizeof (NfitSPATemplate));
+      AcpiNfitFillSPA (NfitSpaPointer, NvdRegionIndex, NvdRegionBase, NvdRegionSize);
+
+      NfitControlRegionPointer = (EFI_ACPI_6_3_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE *)
+                                 (NfitSpaPointer + 1);
+      CopyMem ((VOID *) NfitControlRegionPointer,
+               (VOID *) &NvdimmControlRegionTemplate,
+               sizeof (NvdimmControlRegionTemplate));
+      NfitFillControlRegion (NfitControlRegionPointer, NvdRegionIndex);
+
+      NfitRegionMappingPointer = (EFI_ACPI_6_3_NFIT_NVDIMM_REGION_MAPPING_STRUCTURE *)
+                                 (NfitControlRegionPointer + 1);
+      CopyMem ((VOID *) NfitRegionMappingPointer,
+               (VOID *) &NvdimmRegionMappingTemplate,
+               sizeof (NvdimmRegionMappingTemplate));
+      NfitFillRegionMapping (NfitRegionMappingPointer,
+                             NfitControlRegionPointer,
+                             NfitSpaPointer);
+      /* Next Region */
+      NfitSpaPointer = (EFI_ACPI_6_3_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE *)
+                       (NfitRegionMappingPointer + 1);
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/*
+ * Install NFIT table.
+ */
+EFI_STATUS
+AcpiInstallNfitTable (VOID)
+{
+  EFI_ACPI_6_3_NVDIMM_FIRMWARE_INTERFACE_TABLE                *NfitTablePointer;
+  EFI_ACPI_TABLE_PROTOCOL                                     *AcpiTableProtocol;
+  UINTN                                                       NfitTableKey  = 0;
+  EFI_STATUS                                                  Status;
+  UINTN                                                       Size;
+  UINTN                                                       NvdRegionNum;
+
+  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid,
+                  NULL, (VOID **) &AcpiTableProtocol);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = AcpiGetNvdRegionNumber (&NvdRegionNum);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Size = sizeof (EFI_ACPI_6_3_NVDIMM_FIRMWARE_INTERFACE_TABLE) +
+         ((sizeof (EFI_ACPI_6_3_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE) +
+           sizeof (EFI_ACPI_6_3_NFIT_NVDIMM_REGION_MAPPING_STRUCTURE) +
+           sizeof (EFI_ACPI_6_3_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE)) * NvdRegionNum);
+  NfitTablePointer = (EFI_ACPI_6_3_NVDIMM_FIRMWARE_INTERFACE_TABLE *) AllocateZeroPool (Size);
+  if (NfitTablePointer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  CopyMem ((VOID *) NfitTablePointer,
+           (VOID *) &NFITTableHeaderTemplate,
+           sizeof (NFITTableHeaderTemplate));
+  NfitTablePointer->Header.Length = Size;
+
+  Status = AcpiNfitFillTable (NfitTablePointer);
+  if (EFI_ERROR (Status)) {
+    FreePool ((VOID *) NfitTablePointer);
+    return Status;
+  }
+
+  AcpiTableChecksum ((UINT8 *)NfitTablePointer, NfitTablePointer->Header.Length);
+  Status = AcpiTableProtocol->InstallAcpiTable (AcpiTableProtocol,
+                                                (VOID *) NfitTablePointer,
+                                                NfitTablePointer->Header.Length,
+                                                &NfitTableKey);
+  if (EFI_ERROR (Status)) {
+    FreePool ((VOID *) NfitTablePointer);
+  }
+
+  return Status;
+}
diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPCCT.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPCCT.c
new file mode 100644
index 000000000000..c27e91f06375
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPCCT.c
@@ -0,0 +1,264 @@
+/** @file
+
+  Copyright (c) 2020, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/AcpiPccLib.h>
+#include "AcpiPlatform.h"
+
+EFI_ACPI_6_3_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS PCCTSubspaceTemplate = {
+  2,    /* HW-Reduced Communication Subspace Type 2 */
+  sizeof(EFI_ACPI_6_3_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS),
+  0,    /* DoorbellInterrupt: need fill in */
+  0,
+  0,
+  0,    /* BaseAddress: need fill in */
+  0x100,
+  {0, 0x20, 0, 0x3, 0x0},    /* DoorbellRegister: need fill in */
+  0,
+  0x53000040,
+  1,
+  1,
+  1,
+  {0, 0x20, 0, 0x3, 0x0},    /* DoorbellAckRegister: need fill in */
+  0,
+  0x10001,
+};
+
+EFI_ACPI_6_3_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER PCCTTableHeaderTemplate = {
+  {
+    EFI_ACPI_6_3_PLATFORM_COMMUNICATIONS_CHANNEL_TABLE_SIGNATURE,
+    0, /* need fill in */
+    EFI_ACPI_6_3_PLATFORM_COMMUNICATION_CHANNEL_TABLE_REVISION,    // Revision
+    0x00, // Checksum will be updated at runtime
+    //
+    // It is expected that these values will be updated at EntryPoint.
+    //
+    {0},     // OEM ID is a 6 bytes long field
+    0,       // OEM Table ID(8 bytes long)
+    0,       // OEM Revision
+    0,       // Creator ID
+    0,       // Creator Revision
+  },
+  EFI_ACPI_6_3_PCCT_FLAGS_PLATFORM_INTERRUPT,
+};
+
+STATIC BOOLEAN
+AcpiPcctIsV2 (VOID)
+{
+  CONST EFI_GUID       PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2;
+  VOID                 *Hob;
+
+  /* Get the Platform HOB */
+  Hob = GetFirstGuidHob (&PlatformHobGuid);
+  if (Hob == NULL) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+STATIC UINT32
+AcpiPcctGetNumOfSocket (VOID)
+{
+  UINTN                NumberSockets, NumberActiveSockets, Count, Index, Index1;
+  CONST EFI_GUID       PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2;
+  PlatformInfoHob_V2   *PlatformHob;
+  PlatformClusterEn    *Socket;
+  VOID                 *Hob;
+
+  /* Get the Platform HOB */
+  Hob = GetFirstGuidHob (&PlatformHobGuid);
+  if (Hob == NULL) {
+    return 1;
+  }
+  PlatformHob = (PlatformInfoHob_V2 *) GET_GUID_HOB_DATA (Hob);
+
+  NumberSockets = sizeof (PlatformHob->ClusterEn) / sizeof (PlatformClusterEn);
+  NumberActiveSockets = 0;
+
+  for (Index = 0; Index < NumberSockets; Index++) {
+    Socket = &PlatformHob->ClusterEn[Index];
+    Count = sizeof (Socket->EnableMask) / sizeof (Socket->EnableMask[0]);
+    for (Index1 = 0; Index1 < Count; Index1++) {
+      if (Socket->EnableMask[Index1] != 0) {
+        NumberActiveSockets++;
+        break;
+      }
+    }
+  }
+
+  return NumberActiveSockets;
+}
+
+EFI_STATUS
+AcpiPcctInit (VOID)
+{
+  INTN NumOfSocket = AcpiPcctGetNumOfSocket ();
+  INTN Subspace;
+  INTN Socket;
+
+  for (Socket = 0; Socket < NumOfSocket; Socket++) {
+    for (Subspace = 0; Subspace < PCC_MAX_SUBSPACES_PER_SOCKET; Subspace++ ) {
+      if (AcpiPcctIsV2 ()) {
+        AcpiPccSharedMemInitV2 (Socket, Subspace);
+      } else {
+        AcpiPccSharedMemInit (Socket, Subspace);
+      }
+      AcpiPccSyncSharedMemAddr (Socket, Subspace);
+      AcpiPccUnmaskInt (Socket, Subspace);
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/*
+ *  Install PCCT table.
+ *
+ *  Each socket has 16 PCC subspaces
+ *    0 - 7  : PMPro subspaces
+ *    8 - 15 : SMPro subspaces
+ */
+EFI_STATUS
+AcpiInstallPcctTable (VOID)
+{
+  EFI_ACPI_6_3_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER *PcctTablePointer = NULL;
+  EFI_ACPI_6_3_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS *PcctEntryPointer = NULL;
+  INTN                          NumOfSocket = AcpiPcctGetNumOfSocket ();
+  UINT64                        PccSharedMemPointer = 0;
+  EFI_ACPI_TABLE_PROTOCOL       *AcpiTableProtocol;
+  UINTN                         PcctTableKey  = 0;
+  INTN                          Count, Subspace;
+  INTN                          SubspaceIdx;
+  INTN                          NumOfSubspace;
+  INTN                          IntNum = 0;
+  EFI_STATUS                    Status;
+  UINTN                         Size;
+  INTN                          Socket;
+
+  if (IsAcpiInstalled (EFI_ACPI_6_3_PLATFORM_COMMUNICATIONS_CHANNEL_TABLE_SIGNATURE)) {
+    DEBUG ((DEBUG_INFO, "PCCT table is already installed.  Skipping...\n"));
+    return EFI_ABORTED;
+  }
+
+  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid,
+                  NULL, (VOID **) &AcpiTableProtocol);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  for (Count = 0; Count < gST->NumberOfTableEntries; Count++) {
+    if (CompareGuid (&gArmMpCoreInfoGuid, &(gST->ConfigurationTable[Count].VendorGuid))) {
+      NumOfSubspace = PCC_MAX_SUBSPACES_PER_SOCKET * NumOfSocket;
+
+      Size = sizeof(EFI_ACPI_6_3_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER) +
+                    NumOfSubspace * sizeof(EFI_ACPI_6_3_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS);
+
+      PcctTablePointer = (EFI_ACPI_6_3_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER *)AllocateZeroPool(Size);
+      if (PcctTablePointer == NULL) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      /* Allocation PCC shared memory */
+      AcpiPccAllocSharedMemory (&PccSharedMemPointer, NumOfSubspace);
+      if (PccSharedMemPointer == 0) {
+        FreePool ((VOID *)PcctTablePointer);
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      PcctEntryPointer = (EFI_ACPI_6_3_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS *) ((UINT64) PcctTablePointer +
+          sizeof (EFI_ACPI_6_3_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER));
+
+      for (Socket = 0; Socket < NumOfSocket; Socket++) {
+        for (Subspace = 0; Subspace < PCC_MAX_SUBSPACES_PER_SOCKET; Subspace++ ) {
+          SubspaceIdx = Subspace + PCC_MAX_SUBSPACES_PER_SOCKET * Socket;
+
+          CopyMem (&PcctEntryPointer[SubspaceIdx], &PCCTSubspaceTemplate,
+                  sizeof(EFI_ACPI_6_3_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS));
+
+          PcctEntryPointer[SubspaceIdx].BaseAddress = PccSharedMemPointer +
+                                                      PCC_SUBSPACE_SHARED_MEM_SIZE * SubspaceIdx;
+          PcctEntryPointer[SubspaceIdx].AddressLength = PCC_SUBSPACE_SHARED_MEM_SIZE;
+
+          IntNum = 0;
+          if (Socket > 0) {
+            IntNum = Socket * PLATFORM_SLAVE_SOCKET_SPI_INTERRUPT_START - 32;
+          }
+          if (Subspace < PMPRO_MAX_DB) {
+            IntNum += PMPRO_DB0_IRQ_NUM + Subspace;
+            /* PCC subspaces for 8 PMpro Doorbells */
+            PcctEntryPointer[SubspaceIdx].DoorbellRegister.Address = PMPRO_DBx_REG (Socket, Subspace, DB_OUT);
+            PcctEntryPointer[SubspaceIdx].PlatformInterrupt = IntNum;
+            PcctEntryPointer[SubspaceIdx].PlatformInterruptAckRegister.Address = PMPRO_DBx_REG (Socket, Subspace, DB_STATUS);
+          } else {
+            IntNum += SMPRO_DB0_IRQ_NUM + Subspace - PMPRO_MAX_DB;
+            /* PCC subspaces for 8 SMpro Doorbells */
+            PcctEntryPointer[SubspaceIdx].DoorbellRegister.Address = SMPRO_DBx_REG (Socket,Subspace - PMPRO_MAX_DB, DB_OUT);
+            PcctEntryPointer[SubspaceIdx].PlatformInterrupt = IntNum;
+            PcctEntryPointer[SubspaceIdx].PlatformInterruptAckRegister.Address = SMPRO_DBx_REG (Socket, Subspace - PMPRO_MAX_DB, DB_STATUS);
+          }
+
+          /* Timing */
+          PcctEntryPointer[SubspaceIdx].NominalLatency = PCC_NOMINAL_LATENCY;
+          PcctEntryPointer[SubspaceIdx].MaximumPeriodicAccessRate = PCC_MAX_PERIOD_ACCESS;
+          PcctEntryPointer[SubspaceIdx].MinimumRequestTurnaroundTime = PCC_MIN_REQ_TURNAROUND_TIME;
+
+          /* Initialize subspace used for CPPC queries */
+          if (Subspace == PCC_CPPC_SUBSPACE) {
+            /* Configure CPPC control byte for CPPC : 0x100 */
+            PcctEntryPointer[SubspaceIdx].DoorbellWrite = PCC_MSG | PCC_CPPC_URG_MSG |  PCC_CPPC_MSG;
+            PcctEntryPointer[SubspaceIdx].NominalLatency = PCC_CPPC_NOMINAL_LATENCY;
+            PcctEntryPointer[SubspaceIdx].MinimumRequestTurnaroundTime = PCC_CPPC_MIN_REQ_TURNAROUND_TIME;
+          } else {
+            PcctEntryPointer[SubspaceIdx].DoorbellWrite = PCC_MSG;
+          }
+          if (!AcpiPcctIsV2 ()) {
+            /* Store the upper address (Bit 40-43) of PCC shared memory */
+            PcctEntryPointer[SubspaceIdx].DoorbellWrite |=
+                (PcctEntryPointer[SubspaceIdx].BaseAddress >> 40) & PCP_MSG_UPPER_ADDR_MASK;
+          }
+        }
+      }
+
+      CopyMem (PcctTablePointer, &PCCTTableHeaderTemplate,
+              sizeof (EFI_ACPI_6_3_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER));
+
+      PcctTablePointer->Header.Length = Size;
+      CopyMem (
+        PcctTablePointer->Header.OemId,
+        PcdGetPtr (PcdAcpiDefaultOemId),
+        sizeof (PcctTablePointer->Header.OemId)
+        );
+      PcctTablePointer->Header.OemTableId = EFI_ACPI_OEM_TABLE_ID;
+      PcctTablePointer->Header.OemRevision = 3;
+      PcctTablePointer->Header.CreatorId = EFI_ACPI_CREATOR_ID;
+      PcctTablePointer->Header.CreatorRevision = EFI_ACPI_CREATOR_REVISION;
+
+      AcpiTableChecksum ((UINT8 *) PcctTablePointer,
+                        PcctTablePointer->Header.Length);
+
+      Status = AcpiTableProtocol->InstallAcpiTable (
+                                    AcpiTableProtocol,
+                                    (VOID *) PcctTablePointer,
+                                    PcctTablePointer->Header.Length,
+                                    &PcctTableKey
+                                    );
+      if (EFI_ERROR (Status)) {
+        AcpiPccFreeSharedMemory (&PccSharedMemPointer, NumOfSubspace);
+        FreePool ((VOID *) PcctTablePointer);
+        return Status;
+      }
+      break;
+    }
+  }
+
+  if (Count == gST->NumberOfTableEntries) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPPTT.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPPTT.c
new file mode 100755
index 000000000000..59a8701aa2e7
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPPTT.c
@@ -0,0 +1,338 @@
+/** @file
+
+  Copyright (c) 2020, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "AcpiPlatform.h"
+
+EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR PPTTProcessorTemplate = {
+  EFI_ACPI_6_3_PPTT_TYPE_PROCESSOR,
+  sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR),
+  { EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE },
+  {0}, /* Flags */
+  0, /* Parent */
+  0, /* AcpiProcessorId */
+  0 /* NumberOfPrivateResources */
+};
+
+EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE PPTTCacheTemplate = {
+  EFI_ACPI_6_3_PPTT_TYPE_CACHE,
+  sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE),
+  { EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE },
+  {0}, /* Flags */
+  0, /* NextLevelOfCache */
+  0, /* Size */
+  0, /* NumberOfSets */
+  0, /* Associativity */
+  {0}, /* Attributes */
+  0
+};
+
+EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER PPTTTableHeaderTemplate = {
+  __ACPI_HEADER (
+    EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_STRUCTURE_SIGNATURE,
+    0, /* need fill in */
+    EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_REVISION
+  ),
+};
+
+STATIC EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER *PpttTablePointer;
+STATIC UINT32 PpttCoreOffset[PLATFORM_CPU_MAX_NUM_CORES];
+STATIC UINT32 PpttClusterOffset[PLATFORM_CPU_MAX_CPM * PLATFORM_CPU_MAX_SOCKET];
+STATIC UINT32 PpttSocketOffset[PLATFORM_CPU_MAX_SOCKET];
+STATIC UINT32 PpttRootOffset;
+STATIC UINT32 PpttL1DataCacheOffset[PLATFORM_CPU_MAX_NUM_CORES];
+STATIC UINT32 PpttL1InstructionCacheOffset[PLATFORM_CPU_MAX_NUM_CORES];
+STATIC UINT32 PpttL2CacheOffset[PLATFORM_CPU_MAX_NUM_CORES];
+
+STATIC UINT32
+AcpiPpttProcessorThreadNode (
+  VOID    *EntryPointer,
+  UINT32  CpuId
+  )
+{
+  EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR *PpttProcessorEntryPointer = EntryPointer;
+  UINT32                                *ResPointer;
+  UINTN                                 ClusterIdPerSocket, CoreIdPerCpm, SocketId;
+
+  CopyMem (PpttProcessorEntryPointer, &PPTTProcessorTemplate,
+          sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR));
+
+  ClusterIdPerSocket = (CpuId / PLATFORM_CPU_NUM_CORES_PER_CPM) % PLATFORM_CPU_MAX_CPM;
+  SocketId = (CpuId / PLATFORM_CPU_NUM_CORES_PER_CPM) / PLATFORM_CPU_MAX_CPM;
+  CoreIdPerCpm = CpuId  % PLATFORM_CPU_NUM_CORES_PER_CPM;
+  PpttProcessorEntryPointer->Flags.AcpiProcessorIdValid = 1;
+  PpttProcessorEntryPointer->Flags.NodeIsALeaf = 1;
+  PpttProcessorEntryPointer->Flags.IdenticalImplementation = 1;
+  PpttProcessorEntryPointer->AcpiProcessorId = (SocketId << PLATFORM_SOCKET_UID_BIT_OFFSET) | (ClusterIdPerSocket << 8) | CoreIdPerCpm;
+  PpttProcessorEntryPointer->Parent = (UINT32) PpttCoreOffset[CpuId];
+  PpttProcessorEntryPointer->NumberOfPrivateResources = 2; /* L1I + L1D */
+
+  ResPointer = (UINT32 *) ((UINT64) EntryPointer +
+                          sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR));
+  ResPointer[0] = PpttL1InstructionCacheOffset[CpuId];
+  ResPointer[1] = PpttL1DataCacheOffset[CpuId];
+
+  PpttProcessorEntryPointer->Length = sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR) + 2 * sizeof (UINT32);
+
+  return PpttProcessorEntryPointer->Length;
+}
+
+STATIC UINT32
+AcpiPpttProcessorCoreNode (
+  VOID    *EntryPointer,
+  UINT32  CpuId
+  )
+{
+  EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR *PpttProcessorEntryPointer = EntryPointer;
+
+  PpttCoreOffset[CpuId] = (UINT64) EntryPointer - (UINT64) PpttTablePointer;
+
+  CopyMem (PpttProcessorEntryPointer, &PPTTProcessorTemplate,
+          sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR));
+
+  PpttProcessorEntryPointer->Parent = (UINT32) PpttClusterOffset[CpuId / PLATFORM_CPU_NUM_CORES_PER_CPM];
+  PpttProcessorEntryPointer->Flags.IdenticalImplementation = 1;
+
+  return PpttProcessorEntryPointer->Length;
+}
+
+STATIC UINT32
+AcpiPpttClusterNode (
+  VOID *EntryPointer,
+  UINT32 ClusterId
+  )
+{
+  EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR *PpttProcessorEntryPointer = EntryPointer;
+
+  PpttClusterOffset[ClusterId] = (UINT64) EntryPointer - (UINT64) PpttTablePointer;
+
+  CopyMem (PpttProcessorEntryPointer, &PPTTProcessorTemplate,
+          sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR));
+
+  PpttProcessorEntryPointer->Parent = (UINT32) PpttSocketOffset[ClusterId / PLATFORM_CPU_MAX_CPM];
+  PpttProcessorEntryPointer->Flags.IdenticalImplementation = 1;
+
+  return PpttProcessorEntryPointer->Length;
+}
+
+STATIC UINT32
+AcpiPpttSocketNode (
+  VOID    *EntryPointer,
+  UINT32  SocketId
+  )
+{
+  EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR *PpttProcessorEntryPointer = EntryPointer;
+
+  PpttSocketOffset[SocketId] = (UINT64) EntryPointer - (UINT64) PpttTablePointer;
+
+  CopyMem (PpttProcessorEntryPointer, &PPTTProcessorTemplate,
+          sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR));
+
+  PpttProcessorEntryPointer->Flags.PhysicalPackage = 1;
+  PpttProcessorEntryPointer->Flags.IdenticalImplementation = 1;
+  PpttProcessorEntryPointer->Parent = (UINT32) PpttRootOffset;
+
+  return PpttProcessorEntryPointer->Length;
+}
+
+STATIC UINT32
+AcpiPpttRootNode (
+  VOID *EntryPointer
+  )
+{
+  EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR *PpttProcessorEntryPointer = EntryPointer;
+
+  PpttRootOffset = (UINT64) EntryPointer - (UINT64) PpttTablePointer;
+
+  CopyMem (PpttProcessorEntryPointer, &PPTTProcessorTemplate,
+          sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR));
+
+  PpttProcessorEntryPointer->Flags.IdenticalImplementation = 1;
+
+  return PpttProcessorEntryPointer->Length;
+}
+
+STATIC VOID
+AcpiPpttFillCacheSizeInfo (
+  EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE *Node,
+  UINT32                            Level
+  )
+{
+  UINT64 CacheCCSIDR = AArch64ReadCCSIDRReg (Level);
+  UINT32 CacheLineSize;
+  UINT32 Count;
+
+  CacheLineSize = 1;
+  Count = CCSIDR_LINE_SIZE (CacheCCSIDR) + 4;
+  while (Count-- > 0) {
+    CacheLineSize *= 2;
+  }
+
+  Node->Flags.LineSizeValid = 1;
+  Node->Flags.NumberOfSetsValid = 1;
+  Node->Flags.AssociativityValid = 1;
+  Node->Flags.SizePropertyValid = 1;
+  Node->Flags.CacheTypeValid = 1;
+  Node->NumberOfSets = CCSIDR_NUMSETS (CacheCCSIDR) + 1;
+  Node->Associativity = CCSIDR_ASSOCIATIVITY (CacheCCSIDR) + 1;
+  Node->LineSize = CacheLineSize;
+  Node->Size = Node->NumberOfSets *
+               Node->Associativity *
+               Node->LineSize;
+}
+
+STATIC UINT32
+AcpiPpttL1DataCacheNode (
+  VOID    *EntryPointer,
+  UINT32  CpuId
+  )
+{
+  EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE *PpttCacheEntryPointer = EntryPointer;
+
+  PpttL1DataCacheOffset[CpuId] = (UINT64) EntryPointer - (UINT64) PpttTablePointer;
+  CopyMem (PpttCacheEntryPointer, &PPTTCacheTemplate,
+          sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE));
+
+  AcpiPpttFillCacheSizeInfo (PpttCacheEntryPointer, 1);
+  PpttCacheEntryPointer->Attributes.CacheType = 0x0; /* Data Cache */
+  PpttCacheEntryPointer->NextLevelOfCache = PpttL2CacheOffset[CpuId];
+
+  return PpttCacheEntryPointer->Length;
+}
+
+STATIC UINT32
+AcpiPpttL1InstructionCacheNode (
+  VOID    *EntryPointer,
+  UINT32  CpuId
+  )
+{
+  EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE *PpttCacheEntryPointer = EntryPointer;
+
+  PpttL1InstructionCacheOffset[CpuId] = (UINT64) EntryPointer - (UINT64)PpttTablePointer;
+  CopyMem (PpttCacheEntryPointer, &PPTTCacheTemplate,
+          sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE));
+
+  AcpiPpttFillCacheSizeInfo (PpttCacheEntryPointer, 1);
+  PpttCacheEntryPointer->Attributes.CacheType = 0x1; /* Instruction Cache */
+  PpttCacheEntryPointer->NextLevelOfCache = PpttL2CacheOffset[CpuId];
+
+  return PpttCacheEntryPointer->Length;
+}
+
+STATIC UINT32
+AcpiPpttL2CacheNode (
+  VOID    *EntryPointer,
+  UINT32  CpuId
+  )
+{
+  EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE *PpttCacheEntryPointer = EntryPointer;
+
+  PpttL2CacheOffset[CpuId] = (UINT64) EntryPointer - (UINT64) PpttTablePointer;
+  CopyMem (PpttCacheEntryPointer, &PPTTCacheTemplate,
+          sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE));
+
+  AcpiPpttFillCacheSizeInfo (PpttCacheEntryPointer, 2);
+  PpttCacheEntryPointer->Attributes.CacheType = 0x3; /* Unified Cache */
+  PpttCacheEntryPointer->NextLevelOfCache = 0;
+
+  return PpttCacheEntryPointer->Length;
+}
+
+/*
+ *  Install PPTT table.
+ */
+EFI_STATUS
+AcpiInstallPpttTable (VOID)
+{
+  EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR   *PpttProcessorEntryPointer = NULL;
+  EFI_ACPI_TABLE_PROTOCOL                 *AcpiTableProtocol;
+  UINTN                                   PpttTableKey  = 0;
+  INTN                                    Count, Count1;
+  EFI_STATUS                              Status;
+  UINTN                                   Size;
+
+  if (IsAcpiInstalled (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_STRUCTURE_SIGNATURE)) {
+    DEBUG ((DEBUG_INFO, "PPTT table is already installed.  Skipping...\n"));
+    return EFI_ABORTED;
+  }
+
+  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid,
+                  NULL, (VOID **) &AcpiTableProtocol);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  for (Count = 0; Count < gST->NumberOfTableEntries; Count++) {
+    if (CompareGuid (&gArmMpCoreInfoGuid, &(gST->ConfigurationTable[Count].VendorGuid))) {
+      Size = sizeof (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER) +
+              sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR) + /* Root node */
+              (PLATFORM_CPU_MAX_SOCKET * sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR)) + /* Socket node */
+              (PLATFORM_CPU_MAX_CPM * PLATFORM_CPU_MAX_SOCKET * sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR)) + /* Cluster node */
+              (PLATFORM_CPU_MAX_NUM_CORES * sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR)) + /* Core node */
+              (PLATFORM_CPU_MAX_NUM_CORES * (sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR) + 2 * sizeof (UINT32))) + /* Thread node */
+              (PLATFORM_CPU_MAX_NUM_CORES * sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE)) + /* L1I node */
+              (PLATFORM_CPU_MAX_NUM_CORES * sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE)) + /* L1D node */
+              (PLATFORM_CPU_MAX_NUM_CORES * sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE)); /* L2 node */
+
+      PpttTablePointer =
+        (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER *) AllocateZeroPool (Size);
+      if (PpttTablePointer == NULL) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      PpttProcessorEntryPointer =
+          (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR *) ((UINT64) PpttTablePointer +
+          sizeof (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER));
+
+      Size = 0;
+      Size += AcpiPpttRootNode ((VOID *)((UINT64) PpttProcessorEntryPointer + Size));
+
+      for (Count1 = 0; Count1 < PLATFORM_CPU_MAX_SOCKET; Count1++) {
+        Size += AcpiPpttSocketNode ((VOID *)((UINT64) PpttProcessorEntryPointer + Size), Count1);
+      }
+
+      for (Count1 = 0; Count1 < PLATFORM_CPU_MAX_CPM * PLATFORM_CPU_MAX_SOCKET; Count1++) {
+        Size += AcpiPpttClusterNode ((VOID *)((UINT64) PpttProcessorEntryPointer + Size), Count1);
+      }
+
+      for (Count1 = 0; Count1 < PLATFORM_CPU_MAX_NUM_CORES; Count1++) {
+        Size += AcpiPpttL2CacheNode ((VOID *)((UINT64) PpttProcessorEntryPointer + Size), Count1);
+        Size += AcpiPpttL1InstructionCacheNode ((VOID *) ((UINT64) PpttProcessorEntryPointer + Size), Count1);
+        Size += AcpiPpttL1DataCacheNode ((VOID *)((UINT64) PpttProcessorEntryPointer + Size), Count1);
+        Size += AcpiPpttProcessorCoreNode ((VOID *)((UINT64) PpttProcessorEntryPointer + Size), Count1);
+        Size += AcpiPpttProcessorThreadNode ((VOID *)((UINT64) PpttProcessorEntryPointer + Size), Count1);
+      }
+
+      CopyMem (PpttTablePointer, &PPTTTableHeaderTemplate,
+              sizeof (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER));
+
+      Size += sizeof (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER);
+      PpttTablePointer->Header.Length = Size;
+
+      AcpiTableChecksum ((UINT8 *) PpttTablePointer,
+                        PpttTablePointer->Header.Length);
+
+      Status = AcpiTableProtocol->InstallAcpiTable (
+                                    AcpiTableProtocol,
+                                    (VOID *)PpttTablePointer,
+                                    PpttTablePointer->Header.Length,
+                                    &PpttTableKey
+                                    );
+      FreePool ((VOID *)PpttTablePointer);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+      break;
+    }
+  }
+
+  if (Count == gST->NumberOfTableEntries) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c
index 346f23cbe5fb..31b635db2b7b 100644
--- a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c
+++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c
@@ -47,6 +47,67 @@ AcpiNotificationEvent (
   }
 }
 
+VOID
+EFIAPI
+InstallAcpiOnReadyToBoot (
+  IN EFI_EVENT        Event,
+  IN VOID             *Context
+  )
+{
+  EFI_STATUS Status;
+
+  Status = AcpiInstallMadtTable ();
+  if (!EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "Installed MADT table\n"));
+  }
+
+  Status = AcpiInstallPpttTable ();
+  if (!EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "Installed PPTT table\n"));
+  }
+
+  Status = AcpiInstallSlitTable ();
+  if (!EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "Installed SLIT table\n"));
+  }
+
+  Status = AcpiInstallSratTable ();
+  if (!EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "Installed SRAT table\n"));
+  }
+
+  Status = AcpiInstallPcctTable ();
+  if (!EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "Installed PCCT table\n"));
+  }
+
+  Status = AcpiInstallNfitTable ();
+  if (!EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Installed NFIT table\n"));
+  }
+}
+
+VOID
+EFIAPI
+UpdateAcpiOnExitBootServices(
+  IN EFI_EVENT        Event,
+  IN VOID             *Context
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = AcpiPatchDsdtTable ();
+  if (!EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "DSDT Table updated!\n"));
+  }
+
+  // Configure PCC mailbox base address and unmask interrupt
+  Status = AcpiPcctInit();
+  if (!EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "PCCT Table updated!\n"));
+  }
+}
+
 EFI_STATUS
 EFIAPI
 AcpiPlatformDxeInitialize (
@@ -54,6 +115,10 @@ AcpiPlatformDxeInitialize (
   IN EFI_SYSTEM_TABLE   *SystemTable
   )
 {
+  EFI_EVENT             ReadyToBootEvent;
+  EFI_EVENT             ExitBootServicesEvent;
+  EFI_STATUS            Status;
+
   EfiCreateProtocolNotifyEvent (
     &gEfiAcpiTableProtocolGuid,
     TPL_CALLBACK,
@@ -62,5 +127,24 @@ AcpiPlatformDxeInitialize (
     &mAcpiRegistration
     );
 
+  Status = gBS->CreateEvent (
+                  EVT_SIGNAL_EXIT_BOOT_SERVICES,
+                  TPL_CALLBACK,
+                  UpdateAcpiOnExitBootServices,
+                  NULL,
+                  &ExitBootServicesEvent
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  InstallAcpiOnReadyToBoot,
+                  NULL,
+                  &gEfiEventReadyToBootGuid,
+                  &ReadyToBootEvent
+                  );
+  ASSERT_EFI_ERROR(Status);
+
   return EFI_SUCCESS;
 }
diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSLIT.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSLIT.c
new file mode 100755
index 000000000000..1b69abf9693b
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSLIT.c
@@ -0,0 +1,85 @@
+/** @file
+
+  Copyright (c) 2020, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "AcpiPlatform.h"
+
+#define SELF_DISTANCE                 10
+#define REMOTE_DISTANCE               20
+
+EFI_ACPI_6_3_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_HEADER SLITTableHeaderTemplate = {
+  __ACPI_HEADER (
+    EFI_ACPI_6_3_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE,
+    0, /* need fill in */
+    EFI_ACPI_6_3_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_REVISION
+  ),
+  0,
+};
+
+EFI_STATUS
+AcpiInstallSlitTable (VOID)
+{
+  EFI_ACPI_TABLE_PROTOCOL                                         *AcpiTableProtocol;
+  EFI_STATUS                                                      Status;
+  UINTN                                                           NumDomain, Count, Count1;
+  EFI_ACPI_6_3_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_HEADER  *SlitTablePointer;
+  UINT8                                                           *TmpPtr;
+  UINTN                                                           SlitTableKey;
+  UINTN                                                           NumDomainPerSocket;
+
+  if (IsAcpiInstalled (EFI_ACPI_6_3_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE)) {
+    DEBUG ((DEBUG_INFO, "SLIT table is already installed.  Skipping...\n"));
+    return EFI_ABORTED;
+  }
+
+  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid,
+                  NULL, (VOID **) &AcpiTableProtocol);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  NumDomainPerSocket = CPUGetNumOfSubNuma ();
+  NumDomain = NumDomainPerSocket * GetNumberActiveSockets ();
+
+  SlitTablePointer = (EFI_ACPI_6_3_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_HEADER *)
+                  AllocateZeroPool (sizeof (SLITTableHeaderTemplate) + NumDomain * NumDomain);
+  if (SlitTablePointer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  CopyMem ((VOID *) SlitTablePointer, (VOID *) &SLITTableHeaderTemplate, sizeof (SLITTableHeaderTemplate));
+  SlitTablePointer->NumberOfSystemLocalities = NumDomain;
+  TmpPtr = (UINT8 *) SlitTablePointer + sizeof (SLITTableHeaderTemplate);
+  for (Count = 0; Count < NumDomain; Count++) {
+    for (Count1 = 0; Count1 < NumDomain; Count1++, TmpPtr++) {
+      if (Count == Count1) {
+        *TmpPtr = (UINT8) SELF_DISTANCE;
+        continue;
+      }
+      if ((Count1 / NumDomainPerSocket) == (Count / NumDomainPerSocket)) {
+        *TmpPtr = (UINT8) (SELF_DISTANCE + 1);
+      } else {
+        *TmpPtr = (UINT8) (REMOTE_DISTANCE);
+      }
+    }
+  }
+
+  SlitTablePointer->Header.Length = sizeof (SLITTableHeaderTemplate) + NumDomain * NumDomain;
+
+  AcpiTableChecksum ((UINT8 *) SlitTablePointer,
+                    SlitTablePointer->Header.Length);
+
+  Status = AcpiTableProtocol->InstallAcpiTable (
+                                AcpiTableProtocol,
+                                (VOID *) SlitTablePointer,
+                                SlitTablePointer->Header.Length,
+                                &SlitTableKey
+                                );
+  FreePool ((VOID *) SlitTablePointer);
+
+  return Status;
+}
+
diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSRAT.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSRAT.c
new file mode 100755
index 000000000000..39b6936f6ed0
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSRAT.c
@@ -0,0 +1,268 @@
+/** @file
+
+  Copyright (c) 2020, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Guid/ArmMpCoreInfo.h>
+#include "AcpiPlatform.h"
+
+EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER SRATTableHeaderTemplate = {
+  __ACPI_HEADER (
+    EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE,
+    0, /* need fill in */
+    EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION
+  ),
+  0x00000001,
+  0x0000000000000000,
+};
+
+EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE GicItsAffinityTemplate = {
+  .Type = EFI_ACPI_6_3_GIC_ITS_AFFINITY,
+  sizeof (EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE),
+  .ProximityDomain = 0, /* ProximityDomain */
+  { EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE },
+  .ItsId = 0,
+};
+
+STATIC
+UINTN
+SratCalculateNumMemoryRegion (VOID)
+{
+  EFI_GUID                    PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2;
+  PlatformInfoHob_V2          *PlatformHob;
+  UINTN                       Count;
+  UINT64                      TmpVal;
+  VOID                        *Hob;
+  UINTN                       Result;
+
+  /* Get the Platform HOB */
+  Hob = GetFirstGuidHob (&PlatformHobGuid);
+  if (Hob == NULL) {
+    return 0;
+  }
+  PlatformHob = (PlatformInfoHob_V2 *) GET_GUID_HOB_DATA (Hob);
+
+  Result = 0;
+  for (Count = 0; Count < PlatformHob->DramInfo.NumRegion; Count++) {
+    TmpVal = PlatformHob->DramInfo.Size[Count];
+    if (TmpVal > 0) {
+      Result++;
+    }
+  }
+
+  return Result;
+}
+
+STATIC
+EFI_STATUS
+SratAddMemAffinity (
+  EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE *SratMemAffinity
+  )
+{
+  EFI_GUID                    PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2;
+  PlatformInfoHob_V2          *PlatformHob;
+  UINTN                       Count, NumRegion;
+  UINT64                      RegionSize, RegionBase;
+  VOID                        *Hob;
+  UINTN                       ProximityDomain;
+
+  /* Get the Platform HOB */
+  Hob = GetFirstGuidHob (&PlatformHobGuid);
+  if (Hob == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  PlatformHob = (PlatformInfoHob_V2 *) GET_GUID_HOB_DATA (Hob);
+
+  NumRegion = 0;
+
+  for (Count = 0; Count < PlatformHob->DramInfo.NumRegion; Count++) {
+    RegionSize = PlatformHob->DramInfo.Size[Count];
+    RegionBase = PlatformHob->DramInfo.Base[Count];
+    ProximityDomain = PlatformHob->DramInfo.Node[Count];
+    if (RegionSize > 0) {
+      ZeroMem ((VOID *) &SratMemAffinity[NumRegion], sizeof (SratMemAffinity[NumRegion]));
+      SratMemAffinity[NumRegion].Flags = 1;
+      SratMemAffinity[NumRegion].LengthLow =
+        (UINT32) (RegionSize & 0xFFFFFFFF);
+      SratMemAffinity[NumRegion].LengthHigh =
+        (UINT32) ((RegionSize & 0xFFFFFFFF00000000ULL) >> 32);
+      SratMemAffinity[NumRegion].AddressBaseLow =
+        (UINT32) (RegionBase & 0xFFFFFFFF);
+      SratMemAffinity[NumRegion].AddressBaseHigh =
+        (UINT32) ((RegionBase & 0xFFFFFFFF00000000ULL) >> 32);
+      SratMemAffinity[NumRegion].ProximityDomain = (UINT32) (ProximityDomain);
+      SratMemAffinity[NumRegion].Type = EFI_ACPI_6_3_MEMORY_AFFINITY;
+      SratMemAffinity[NumRegion].Length = sizeof (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE);
+      NumRegion++;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+SratAddGiccAffinity (
+  EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE *SratGiccAffinity
+  )
+{
+  ARM_PROCESSOR_TABLE                                     *ArmProcessorTable;
+  ARM_CORE_INFO                                           *ArmCoreInfoTable;
+  UINTN                                                   Count, NumNode, Idx;
+  UINT32                                                  AcpiProcessorUid;
+  UINT8                                                   Socket;
+  UINT8                                                   Cpm;
+
+  for (Idx = 0; Idx < gST->NumberOfTableEntries; Idx++) {
+    if (CompareGuid (&gArmMpCoreInfoGuid, &(gST->ConfigurationTable[Idx].VendorGuid))) {
+      ArmProcessorTable = (ARM_PROCESSOR_TABLE *) gST->ConfigurationTable[Idx].VendorTable;
+      ArmCoreInfoTable = ArmProcessorTable->ArmCpus;
+      break;
+    }
+  }
+
+  if (Idx == gST->NumberOfTableEntries) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Count = 0;
+  NumNode = 0;
+  while (Count != ArmProcessorTable->NumberOfEntries) {
+    for (Idx = 0; Idx < ArmProcessorTable->NumberOfEntries; Idx++ ) {
+      Socket = ArmCoreInfoTable[Idx].ClusterId;
+      Cpm = (ArmCoreInfoTable[Idx].CoreId >> PLATFORM_CPM_UID_BIT_OFFSET);
+      if (CPUGetSubNumNode (Socket, Cpm) != NumNode) {
+        /* We add nodes based on ProximityDomain order */
+        continue;
+      }
+      AcpiProcessorUid = (ArmCoreInfoTable[Idx].ClusterId << PLATFORM_SOCKET_UID_BIT_OFFSET) +
+                        ArmCoreInfoTable[Idx].CoreId;
+      ZeroMem ((VOID *) &SratGiccAffinity[Count], sizeof (SratGiccAffinity[Count]));
+      SratGiccAffinity[Count].AcpiProcessorUid = AcpiProcessorUid;
+      SratGiccAffinity[Count].Flags = 1;
+      SratGiccAffinity[Count].Length = sizeof (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE);
+      SratGiccAffinity[Count].Type = EFI_ACPI_6_3_GICC_AFFINITY;
+      SratGiccAffinity[Count].ProximityDomain = CPUGetSubNumNode (Socket, Cpm);
+      Count++;
+    }
+    NumNode++;
+  }
+
+  return EFI_SUCCESS;
+}
+
+STATIC UINT32
+InstallGicItsAffinity (
+  VOID    *EntryPointer,
+  UINT32  Index
+  )
+{
+  EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE *ItsAffinityEntryPointer = EntryPointer;
+  UINTN Size;
+
+  Size = sizeof (GicItsAffinityTemplate);
+  CopyMem (ItsAffinityEntryPointer, &GicItsAffinityTemplate, Size);
+  return Size;
+}
+
+STATIC
+EFI_STATUS
+SratAddGicItsAffinity (
+  VOID *TmpPtr
+  )
+{
+  UINTN Size = 0;
+  UINTN Index;
+
+  /* Install Gic ITSAffinity */
+  if (!PlatSlaveSocketPresent ()) {
+    for (Index = 0; Index <= 1; Index++) { /* RCA0/1 */
+      GicItsAffinityTemplate.ItsId = Index;
+      GicItsAffinityTemplate.ProximityDomain = 0;
+      Size += InstallGicItsAffinity ((VOID *) ((UINT64) TmpPtr + Size), Index);
+    }
+  }
+
+  for (Index = SOCKET0_FIRST_RC; Index <= SOCKET0_LAST_RC; Index++) {
+      GicItsAffinityTemplate.ItsId = Index;
+      GicItsAffinityTemplate.ProximityDomain = 0;
+    Size += InstallGicItsAffinity ((VOID *) ((UINT64) TmpPtr + Size), Index);
+  }
+
+  if (GetNumberActiveSockets () > 1) {
+    for (Index = SOCKET1_FIRST_RC; Index <= SOCKET1_LAST_RC; Index++) {
+      GicItsAffinityTemplate.ItsId = Index;
+      GicItsAffinityTemplate.ProximityDomain = 1;
+      Size += InstallGicItsAffinity ((VOID *) ((UINT64) TmpPtr + Size), Index);
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AcpiInstallSratTable (VOID)
+{
+  EFI_ACPI_TABLE_PROTOCOL                               *AcpiTableProtocol;
+  EFI_STATUS                                            Status;
+  EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER    *SratTablePointer;
+  UINT8                                                 *TmpPtr;
+  UINTN                                                 SratTableKey;
+  UINTN                                                 Size;
+
+  if (IsAcpiInstalled (EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE)) {
+    DEBUG ((DEBUG_INFO, "SRAT table is already installed.  Skipping...\n"));
+    return EFI_ABORTED;
+  }
+
+  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid,
+                  NULL, (VOID **) &AcpiTableProtocol);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Size = sizeof (SRATTableHeaderTemplate) +
+                    SratCalculateNumMemoryRegion () * sizeof (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE) +
+                    GetNumberActiveCores () * sizeof (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE) +
+                    ((SOCKET0_LAST_RC - SOCKET0_FIRST_RC +  1) * sizeof (GicItsAffinityTemplate));
+      if (GetNumberActiveSockets () > 1) {
+        Size += (SOCKET1_LAST_RC - SOCKET1_FIRST_RC +  1) * sizeof (GicItsAffinityTemplate);
+      } else if (!PlatSlaveSocketPresent ()){
+        Size += 2 * sizeof(GicItsAffinityTemplate); /* RCA0/1 */
+      }
+
+  SratTablePointer = (EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *) AllocateZeroPool (Size);
+  if (SratTablePointer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  CopyMem ((VOID *) SratTablePointer, (VOID *) &SRATTableHeaderTemplate, sizeof (SRATTableHeaderTemplate));
+
+  TmpPtr = (UINT8 *) SratTablePointer + sizeof (SRATTableHeaderTemplate);
+  Status = SratAddMemAffinity ((EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE *) TmpPtr);
+  ASSERT_EFI_ERROR (Status);
+
+  TmpPtr += SratCalculateNumMemoryRegion () * sizeof (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE);
+  Status = SratAddGiccAffinity ((EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE *) TmpPtr);
+  ASSERT_EFI_ERROR (Status);
+
+  TmpPtr += GetNumberActiveCores () * sizeof (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE);
+  SratAddGicItsAffinity ((VOID*) (UINT64) TmpPtr);
+  SratTablePointer->Header.Length = Size;
+
+  AcpiTableChecksum ((UINT8 *) SratTablePointer,
+                    SratTablePointer->Header.Length);
+
+  Status = AcpiTableProtocol->InstallAcpiTable (
+                                AcpiTableProtocol,
+                                (VOID *) SratTablePointer,
+                                SratTablePointer->Header.Length,
+                                &SratTableKey
+                                );
+  FreePool ((VOID *) SratTablePointer);
+
+  return Status;
+}
+
-- 
2.17.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#68508): https://edk2.groups.io/g/devel/message/68508
Mute This Topic: https://groups.io/mt/78825492/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list