From: "Nhi Pham" <nhi@os.amperecomputing.com>
To: devel@edk2.groups.io
Cc: Nhi Pham <nhi@os.amperecomputing.com>
Subject: [edk2-platforms][PATCH 09/34] JadePkg: Install some ACPI tables at runtime
Date: Wed, 9 Dec 2020 16:25:06 +0700 [thread overview]
Message-ID: <20201209092531.30867-10-nhi@os.amperecomputing.com> (raw)
In-Reply-To: <20201209092531.30867-1-nhi@os.amperecomputing.com>
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@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
next prev parent reply other threads:[~2020-12-09 9:24 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-09 9:24 [edk2-platforms][PATCH 00/34] Add new Ampere Mt. Jade platform Nhi Pham
2020-12-09 9:24 ` [edk2-platforms][PATCH 01/34] Initial support for Ampere Altra and " Nhi Pham
2021-01-07 23:57 ` [edk2-devel] " Leif Lindholm
2021-01-15 4:59 ` Vu Nguyen
2020-12-09 9:24 ` [edk2-platforms][PATCH 02/34] Platform/Ampere: Implement FailSafe library Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 03/34] Platform/Ampere: Add FailSafe and WDT support Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 04/34] AmpereAltraPkg: Implement GpioLib and I2cLib modules Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 05/34] JadePkg: Implement RealTimeClockLib for PCF85063 Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 06/34] Platform/Ampere: Add AcpiPccLib to support ACPI PCCT Table Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 07/34] Platform/Ampere: Add AcpiHelperLib to update ACPI DSDT table Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 08/34] JadePkg: Initial support for static ACPI tables Nhi Pham
2020-12-09 9:25 ` Nhi Pham [this message]
2020-12-09 9:25 ` [edk2-platforms][PATCH 10/34] Silicon/Ampere: Support Non Volatile storage for Variable service Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 11/34] Silicon/Ampere: Support PlatformManagerUiLib Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 12/34] AmpereAltraPkg: Add PcieCore Library Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 13/34] AmpereAltraPkg: Add PciHostBridge driver Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 14/34] JadePkg: Add implementation for PcieBoardLib Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 15/34] JadePkg: Enable PCIe support Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 16/34] JadePkg: Add ASpeed GOP driver Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 17/34] Silicon/Ampere: Add Random Number Generator Support Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 18/34] Silicon/Ampere: Fixup runtime memory attribute Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 19/34] JadePkg: Add SMBIOS tables support Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 20/34] AmpereAltraPkg: Add DebugInfoPei module Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 21/34] Silicon/Ampere: Add platform info screen Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 22/34] Silicon/Ampere: Add Memory " Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 23/34] AmpereAltraPkg: Add CPU Configuration for SubNUMA Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 24/34] AmpereAltraPkg: Add ACPI configuration screen Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 25/34] AmpereAltraPkg: Implement PlatformFlashAccessLib instance Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 26/34] JadePkg: Add implementation for UEFI Capsule Update Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 27/34] JadePkg: Add Capsule Update support Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 28/34] Silicon/Ampere: Implement PlatformBootManagerLib for LinuxBoot Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 29/34] Platform/Ampere: Add LinuxBoot image Nhi Pham
2020-12-10 12:40 ` [edk2-devel] " Leif Lindholm
2020-12-11 2:38 ` Nhi Pham
2020-12-11 11:15 ` Leif Lindholm
2020-12-09 9:25 ` [edk2-platforms][PATCH 30/34] JadePkg: Support LinuxBoot DSC/FDF build for Jade platform Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 31/34] AmpereAltraPkg: Add BootProgress support Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 32/34] JadePkg: Add ACPI/APEI tables Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 33/34] Platform/Ampere: Add AcpiApeiLib Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 34/34] AmpereAltraPkg, JadePkg: Add RAS setting screen Nhi Pham
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201209092531.30867-10-nhi@os.amperecomputing.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox