123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367 |
- /** @file
- Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <AcpiHeader.h>
- #include <Guid/RootComplexConfigHii.h>
- #include <Guid/RootComplexInfoHob.h>
- #include <IndustryStandard/Acpi30.h>
- #include <IndustryStandard/IoRemappingTable.h>
- #include <Library/AcpiLib.h>
- #include <Library/AmpereCpuLib.h>
- #include <Library/BaseMemoryLib.h>
- #include <Library/DebugLib.h>
- #include <Library/HobLib.h>
- #include <Library/MemoryAllocationLib.h>
- #include <Library/UefiBootServicesTableLib.h>
- #include <Library/UefiRuntimeServicesTableLib.h>
- #include <Platform/Ac01.h>
- #include <Protocol/AcpiTable.h>
- #define __AC01_ID_MAPPING(In, Num, Out, Ref, Flags) \
- { \
- In, \
- Num, \
- Out, \
- OFFSET_OF (AC01_IO_REMAPPING_STRUCTURE, Ref), \
- Flags \
- }
- #define TCU_TO_SMMU_OFFSET 0x2000
- #define PAGE1_TO_PMCG_OFFSET 0x10000
- STATIC AC01_ROOT_COMPLEX *mRootComplexList;
- STATIC UINT32 mTbuPmuIrqArray[] = { AC01_SMMU_TBU_PMU_IRQS_LIST };
- STATIC UINT32 mTcuPmuIrqArray[] = { AC01_SMMU_TCU_PMU_IRQS_LIST };
- STATIC UINT64 mRcaTbuPmuOffset[] = { AC01_RCA_TBU_PMU_OFFSET_LIST };
- STATIC UINT64 mRcbTbuPmuOffset[] = { AC01_RCB_TBU_PMU_OFFSET_LIST };
- #pragma pack(1)
- typedef struct {
- EFI_ACPI_6_0_IO_REMAPPING_NODE Node;
- UINT64 Base;
- UINT32 Flags;
- UINT32 Reserved;
- UINT64 VatosAddress;
- UINT32 Model;
- UINT32 Event;
- UINT32 Pri;
- UINT32 Gerr;
- UINT32 Sync;
- UINT32 ProximityDomain;
- UINT32 DeviceIdMapping;
- } EFI_ACPI_6_2_IO_REMAPPING_SMMU3_NODE;
- typedef struct {
- EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE Node;
- UINT32 ItsIdentifier;
- } AC01_ITS_NODE;
- typedef struct {
- EFI_ACPI_6_0_IO_REMAPPING_RC_NODE Node;
- EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE RcIdMapping;
- } AC01_RC_NODE;
- typedef struct {
- EFI_ACPI_6_2_IO_REMAPPING_SMMU3_NODE Node;
- EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE InterruptMsiMapping;
- EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE InterruptMsiMappingSingle;
- } AC01_SMMU_NODE;
- typedef struct {
- EFI_ACPI_6_0_IO_REMAPPING_TABLE Iort;
- AC01_ITS_NODE ItsNode[2];
- AC01_RC_NODE RcNode[2];
- AC01_SMMU_NODE SmmuNode[2];
- } AC01_IO_REMAPPING_STRUCTURE;
- #pragma pack()
- EFI_ACPI_6_0_IO_REMAPPING_TABLE mIortHeader = {
- .Header = __ACPI_HEADER (
- EFI_ACPI_6_0_IO_REMAPPING_TABLE_SIGNATURE,
- AC01_IO_REMAPPING_STRUCTURE,
- EFI_ACPI_IO_REMAPPING_TABLE_REVISION_00
- ),
- .NumNodes = 0, // To be filled
- .NodeOffset = sizeof (EFI_ACPI_6_0_IO_REMAPPING_TABLE),
- 0
- };
- AC01_ITS_NODE mItsNodeTemplate = {
- .Node = {
- {
- EFI_ACPI_IORT_TYPE_ITS_GROUP,
- sizeof (EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE) + 4,
- 0x0,
- 0x0,
- 0x0,
- 0x0,
- },
- .NumItsIdentifiers = 1,
- },
- .ItsIdentifier = 1,
- };
- AC01_RC_NODE mRcNodeTemplate = {
- {
- {
- EFI_ACPI_IORT_TYPE_ROOT_COMPLEX,
- sizeof (AC01_RC_NODE),
- 0x1,
- 0x0,
- 0x1,
- OFFSET_OF (AC01_RC_NODE, RcIdMapping),
- },
- EFI_ACPI_IORT_MEM_ACCESS_PROP_CCA,
- 0x0,
- 0x0,
- EFI_ACPI_IORT_MEM_ACCESS_FLAGS_CPM |
- EFI_ACPI_IORT_MEM_ACCESS_FLAGS_DACS,
- EFI_ACPI_IORT_ROOT_COMPLEX_ATS_UNSUPPORTED,
- .PciSegmentNumber = 0,
- .MemoryAddressSize = 64,
- },
- __AC01_ID_MAPPING (0x0, 0xffff, 0x0, SmmuNode, 0),
- };
- AC01_SMMU_NODE mSmmuNodeTemplate = {
- {
- {
- EFI_ACPI_IORT_TYPE_SMMUv3,
- sizeof (AC01_SMMU_NODE),
- 0x2, // Revision
- 0x0,
- 0x2, // Mapping Count
- OFFSET_OF (AC01_SMMU_NODE, InterruptMsiMapping),
- },
- .Base = 0,
- EFI_ACPI_IORT_SMMUv3_FLAG_COHAC_OVERRIDE | EFI_ACPI_IORT_SMMUv3_FLAG_PROXIMITY_DOMAIN,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0x0,
- 0x0,
- 0, // Proximity domain - need fill in
- .DeviceIdMapping = 1,
- },
- __AC01_ID_MAPPING (0x0, 0xffff, 0, SmmuNode, 0),
- __AC01_ID_MAPPING (0x0, 0x1, 0, SmmuNode, 1),
- };
- EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE mPmcgNodeTemplate = {
- {
- EFI_ACPI_IORT_TYPE_PMCG,
- sizeof (EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE),
- 0x1,
- 0x0,
- 0x0,
- 0x0,
- },
- 0, // Page 0 Base. Need to be filled
- 0, // GSIV. Need to be filled
- 0, // Node reference. Need to be filled
- 0, // Page 1 Base. Need to be filled
- };
- STATIC
- VOID
- ConstructIort (
- VOID *IortBuffer,
- UINT32 RcCount,
- UINT32 SmmuPmuAgentCount,
- UINT32 HeaderCount,
- INT32 *EnabledRCs
- )
- {
- AC01_ROOT_COMPLEX *RootComplex;
- UINT32 Idx, Idx1;
- UINT32 ItsOffset[AC01_PCIE_MAX_ROOT_COMPLEX];
- UINT32 SmmuNodeOffset[AC01_PCIE_MAX_ROOT_COMPLEX];
- UINT64 *TbuPmuOffset;
- UINTN MaxTbuPmu;
- VOID *IortIter, *SmmuIter, *PmcgIter;
- IortIter = IortBuffer;
- mIortHeader.Header.Length = HeaderCount;
- mIortHeader.NumNodes = (3 * RcCount) + SmmuPmuAgentCount,
- CopyMem (IortIter, &mIortHeader, sizeof (EFI_ACPI_6_0_IO_REMAPPING_TABLE));
- IortIter += sizeof (EFI_ACPI_6_0_IO_REMAPPING_TABLE);
- for (Idx = 0; Idx < RcCount; Idx++) {
- ItsOffset[Idx] = IortIter - IortBuffer;
- mItsNodeTemplate.ItsIdentifier = EnabledRCs[Idx];
- CopyMem (IortIter, &mItsNodeTemplate, sizeof (AC01_ITS_NODE));
- IortIter += sizeof (AC01_ITS_NODE);
- }
- SmmuIter = IortIter + RcCount * sizeof (AC01_RC_NODE);
- PmcgIter = SmmuIter + RcCount * sizeof (AC01_SMMU_NODE);
- for (Idx = 0; Idx < RcCount; Idx++) {
- SmmuNodeOffset[Idx] = SmmuIter - IortBuffer;
- RootComplex = &mRootComplexList[EnabledRCs[Idx]];
- mSmmuNodeTemplate.Node.Base = RootComplex->TcuBase;
- mSmmuNodeTemplate.InterruptMsiMapping.OutputBase = EnabledRCs[Idx] << 16;
- mSmmuNodeTemplate.InterruptMsiMapping.OutputReference = ItsOffset[Idx];
- mSmmuNodeTemplate.InterruptMsiMappingSingle.OutputBase = EnabledRCs[Idx] << 16;
- mSmmuNodeTemplate.InterruptMsiMappingSingle.OutputReference = ItsOffset[Idx];
- /* All RCs on master be assigned to node 0, while remote RCs will be assigned to first remote node */
- mSmmuNodeTemplate.Node.ProximityDomain = 0;
- if ((RootComplex->TcuBase & SLAVE_SOCKET_BASE_ADDRESS_OFFSET) != 0) {
- // RootComplex on remote socket
- switch (CpuGetSubNumaMode ()) {
- case SUBNUMA_MODE_MONOLITHIC:
- mSmmuNodeTemplate.Node.ProximityDomain += MONOLITIC_NUM_OF_REGION;
- break;
- case SUBNUMA_MODE_HEMISPHERE:
- mSmmuNodeTemplate.Node.ProximityDomain += HEMISPHERE_NUM_OF_REGION;
- break;
- case SUBNUMA_MODE_QUADRANT:
- mSmmuNodeTemplate.Node.ProximityDomain += QUADRANT_NUM_OF_REGION;
- break;
- }
- }
- CopyMem (SmmuIter, &mSmmuNodeTemplate, sizeof (AC01_SMMU_NODE));
- SmmuIter += sizeof (AC01_SMMU_NODE);
- if (SmmuPmuAgentCount == 0) {
- continue;
- }
- //
- // Add TBU PMCG nodes
- //
- if (RootComplex->Type == RootComplexTypeA) {
- MaxTbuPmu = AC01_RCA_MAX_TBU_PMU;
- TbuPmuOffset = mRcaTbuPmuOffset;
- } else {
- MaxTbuPmu = AC01_RCB_MAX_TBU_PMU;
- TbuPmuOffset = mRcbTbuPmuOffset;
- }
- for (Idx1 = 0; Idx1 < MaxTbuPmu; Idx1++) {
- mPmcgNodeTemplate.Base = RootComplex->TcuBase + TCU_TO_SMMU_OFFSET + TbuPmuOffset[Idx1];
- mPmcgNodeTemplate.Page1Base = mPmcgNodeTemplate.Base + PAGE1_TO_PMCG_OFFSET;
- mPmcgNodeTemplate.NodeReference = SmmuNodeOffset[Idx];
- mPmcgNodeTemplate.OverflowInterruptGsiv = mTbuPmuIrqArray[EnabledRCs[Idx]] + Idx1;
- CopyMem (PmcgIter, &mPmcgNodeTemplate, sizeof (mPmcgNodeTemplate));
- PmcgIter += sizeof (mPmcgNodeTemplate);
- }
- //
- // Add TCU PMCG node
- //
- mPmcgNodeTemplate.Base = RootComplex->TcuBase + TCU_TO_SMMU_OFFSET;
- mPmcgNodeTemplate.Page1Base = mPmcgNodeTemplate.Base + PAGE1_TO_PMCG_OFFSET;
- mPmcgNodeTemplate.NodeReference = SmmuNodeOffset[Idx];
- mPmcgNodeTemplate.OverflowInterruptGsiv = mTcuPmuIrqArray[EnabledRCs[Idx]];
- CopyMem (PmcgIter, &mPmcgNodeTemplate, sizeof (mPmcgNodeTemplate));
- PmcgIter += sizeof (mPmcgNodeTemplate);
- }
- for (Idx = 0; Idx < RcCount; Idx++) {
- mRcNodeTemplate.Node.PciSegmentNumber = mRootComplexList[EnabledRCs[Idx]].Logical;
- mRcNodeTemplate.RcIdMapping.OutputReference = SmmuNodeOffset[Idx];
- CopyMem (IortIter, &mRcNodeTemplate, sizeof (AC01_RC_NODE));
- IortIter += sizeof (AC01_RC_NODE);
- }
- }
- EFI_STATUS
- EFIAPI
- AcpiInstallIort (
- VOID
- )
- {
- EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
- EFI_STATUS Status;
- INT32 EnabledRCs[AC01_PCIE_MAX_ROOT_COMPLEX];
- ROOT_COMPLEX_CONFIG_VARSTORE_DATA VarStoreConfig;
- UINT32 RcCount, SmmuPmuAgentCount, TotalCount;
- UINT8 Idx;
- UINTN BufferSize;
- UINTN TableKey;
- VOID *Hob;
- VOID *IortBuffer;
- Hob = GetFirstGuidHob (&gRootComplexInfoHobGuid);
- if (Hob == NULL) {
- return EFI_NOT_FOUND;
- }
- mRootComplexList = (AC01_ROOT_COMPLEX *)GET_GUID_HOB_DATA (Hob);
- for (Idx = 0, RcCount = 0; Idx < AC01_PCIE_MAX_ROOT_COMPLEX; Idx++) {
- if (mRootComplexList[Idx].Active) {
- EnabledRCs[RcCount++] = Idx;
- }
- }
- EnabledRCs[RcCount] = -1;
- Status = gBS->LocateProtocol (
- &gEfiAcpiTableProtocolGuid,
- NULL,
- (VOID **)&AcpiTableProtocol
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "IORT: Unable to locate ACPI table entry\n"));
- return Status;
- }
- SmmuPmuAgentCount = 0;
- //
- // Check SMMU setting
- //
- BufferSize = sizeof (VarStoreConfig);
- Status = gRT->GetVariable (
- ROOT_COMPLEX_CONFIG_VARSTORE_NAME,
- &gRootComplexConfigFormSetGuid,
- NULL,
- &BufferSize,
- &VarStoreConfig
- );
- if (!EFI_ERROR (Status) && VarStoreConfig.SmmuPmu) {
- for (Idx = 0; Idx < RcCount; Idx++) {
- if (mRootComplexList[EnabledRCs[Idx]].Type == RootComplexTypeA) {
- SmmuPmuAgentCount += AC01_RCA_MAX_TBU_PMU;
- } else {
- SmmuPmuAgentCount += AC01_RCB_MAX_TBU_PMU;
- }
- // Plus 1 TCU
- SmmuPmuAgentCount += 1;
- }
- }
- TotalCount = sizeof (EFI_ACPI_6_0_IO_REMAPPING_TABLE) +
- RcCount * (sizeof (AC01_ITS_NODE) + sizeof (AC01_RC_NODE) + sizeof (AC01_SMMU_NODE)) +
- SmmuPmuAgentCount * sizeof (EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE);
- IortBuffer = AllocateZeroPool (TotalCount);
- if (IortBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- ConstructIort (IortBuffer, RcCount, SmmuPmuAgentCount, TotalCount, EnabledRCs);
- Status = AcpiTableProtocol->InstallAcpiTable (
- AcpiTableProtocol,
- IortBuffer,
- TotalCount,
- &TableKey
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "IORT: Unable to install IORT table entry\n"));
- }
- FreePool (IortBuffer);
- return Status;
- }
|