/** @file Copyright (c) 2020 - 2023, Ampere Computing LLC. All rights reserved.
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, AC01_GICR_MASTER_BASE_ADDRESS, /* 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 */ AC01_GICD_MASTER_BASE_ADDRESS, /* 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 ), }; EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *MadtTablePointer; 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 = SOCKET_ID (CpuId); ClusterId = CLUSTER_ID (CpuId); // // GICv2 compatibility mode is not supported. // Hence, set GIC's CPU Interface Number to 0. // MadtProcessorEntryPointer->CPUInterfaceNumber = 0; 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; } UINT32 AcpiInstallMadtGicD ( VOID *EntryPointer ) { EFI_ACPI_6_3_GIC_DISTRIBUTOR_STRUCTURE *GicDEntryPointer = EntryPointer; UINTN Size; Size = sizeof (GicDTemplate); CopyMem (GicDEntryPointer, &GicDTemplate, Size); return Size; } 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 && !IsSlaveSocketActive ()) { return 0; } Size = sizeof (GicRTemplate); CopyMem (GicREntryPointer, &GicRTemplate, Size); if (SocketId == 1) { GicREntryPointer->DiscoveryRangeBaseAddress = AC01_GICR_SLAVE_BASE_ADDRESS; } return Size; } UINT32 AcpiInstallMadtGicIts ( VOID *EntryPointer, UINT32 Index ) { EFI_ACPI_6_3_GIC_ITS_STRUCTURE *GicItsEntryPointer = EntryPointer; UINTN Size, Offset; UINT64 GicBase = AC01_GICD_MASTER_BASE_ADDRESS; UINT32 ItsId = Index; if (Index > SOCKET0_LAST_RC) { /* Socket 1, Index: 8-15 */ GicBase = AC01_GICD_SLAVE_BASE_ADDRESS; 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 Index; EFI_STATUS Status; UINTN Size; UINTN Length; UINT32 *CoreOrder; UINT32 SktMaxCoreNum; Status = gBS->LocateProtocol ( &gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTableProtocol ); if (EFI_ERROR (Status)) { return Status; } Size = sizeof (MADTTableHeaderTemplate) + sizeof (GiccTemplate) * GetNumberOfActiveCores () + sizeof (GicDTemplate) + sizeof (GicRTemplate) * GetNumberOfActiveSockets () + sizeof (GicItsTemplate) * (SOCKET0_LAST_RC - SOCKET0_FIRST_RC + 1); if (IsSlaveSocketActive ()) { Size += (sizeof (GicItsTemplate) * (SOCKET1_LAST_RC - SOCKET1_FIRST_RC + 1)); } else if (!IsSlaveSocketAvailable ()) { Size += sizeof (GicItsTemplate) * 2; /* 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 */ Length = 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])) { Length += AcpiInstallMadtProcessorNode ((VOID *)((UINT64)GiccEntryPointer + Length), CoreOrder[Index]); } } for (Index = 0; Index < SktMaxCoreNum; Index++) { if (IsCpuEnabled (CoreOrder[Index] + SktMaxCoreNum)) { Length += AcpiInstallMadtProcessorNode ((VOID *)((UINT64)GiccEntryPointer + Length), CoreOrder[Index] + SktMaxCoreNum); } } /* Install Gic Distributor */ Length += AcpiInstallMadtGicD ((VOID *)((UINT64)GiccEntryPointer + Length)); /* Install Gic Redistributor */ for (Index = 0; Index < PLATFORM_CPU_MAX_SOCKET; Index++) { Length += AcpiInstallMadtGicR ((VOID *)((UINT64)GiccEntryPointer + Length), Index); } /* Install Gic ITS */ if (!IsSlaveSocketAvailable ()) { for (Index = 0; Index <= 1; Index++) { /* RCA0/1 */ Length += AcpiInstallMadtGicIts ((VOID *)((UINT64)GiccEntryPointer + Length), Index); } } for (Index = SOCKET0_FIRST_RC; Index <= SOCKET0_LAST_RC; Index++) { Length += AcpiInstallMadtGicIts ((VOID *)((UINT64)GiccEntryPointer + Length), Index); } if (IsSlaveSocketActive ()) { for (Index = SOCKET1_FIRST_RC; Index <= SOCKET1_LAST_RC; Index++) { Length += AcpiInstallMadtGicIts ((VOID *)((UINT64)GiccEntryPointer + Length), Index); } } CopyMem ( MadtTablePointer, &MADTTableHeaderTemplate, sizeof (MADTTableHeaderTemplate) ); Length += sizeof (MADTTableHeaderTemplate); MadtTablePointer->Header.Length = Length; ASSERT (Size == Length); CopyMem ( MadtTablePointer->Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (MadtTablePointer->Header.OemId) ); AcpiUpdateChecksum ((UINT8 *)MadtTablePointer, MadtTablePointer->Header.Length); Status = AcpiTableProtocol->InstallAcpiTable ( AcpiTableProtocol, (VOID *)MadtTablePointer, MadtTablePointer->Header.Length, &MadtTableKey ); FreePool ((VOID *)MadtTablePointer); if (EFI_ERROR (Status)) { return Status; } return EFI_SUCCESS; }