123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146 |
- /** @file
- ACPI Platform Driver Hooks
- @copyright
- Copyright 1996 - 2020 Intel Corporation. <BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- //
- // Statements that include other files
- //
- #include "AcpiPlatformLibLocal.h"
- extern SYSTEM_MEMORY_MAP_HOB *mSystemMemoryMap;
- extern EFI_IIO_UDS_PROTOCOL *mIioUds;
- extern EFI_ACPI_TABLE_PROTOCOL *mAcpiTable;
- extern CPU_CSR_ACCESS_VAR *mCpuCsrAccessVarPtr;
- EFI_ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE_PMEM_INFO mSlitPmemInfo[EFI_ACPI_SLIT_PMEM_INFO_CNT];
- /**
- Displays System Locality Distance Information Table (SLIT)
- @param None
- @retval None
- **/
- VOID
- DisplayEntries (
- IN ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitPtr
- )
- {
- UINT16 EntryIdx = 0;
- UINT16 MaxTableEntries;
- UINT8 NodeCount;
- if (SlitPtr == NULL) {
- ASSERT (SlitPtr != NULL);
- return;
- }
- NodeCount = (UINT8)SlitPtr->Header.NumberOfSystemLocalities;
- MaxTableEntries = NodeCount * NodeCount;
- DEBUG ((DEBUG_INFO, "SLIT: Dump table (size %d):\n", NodeCount));
- while (EntryIdx < MaxTableEntries) {
- DEBUG ((DEBUG_INFO, "%02X ", SlitPtr->NumSlit[EntryIdx].Entry));
- if ((EntryIdx % NodeCount) == (NodeCount - 1)) {
- DEBUG ((DEBUG_INFO, "\n"));
- }
- EntryIdx++;
- }
- }
- /**
- Stores correlation between AEP PMEM NUMA node and socket
- @param[in] Pmem AEP PMEM NUMA node number
- @param[in] Socket Socket number
- @retval None
- **/
- VOID
- SavePmemInfo (
- IN UINT8 Pmem,
- IN UINT8 Socket,
- MEM_TYPE Type
- )
- {
- if (Pmem < EFI_ACPI_SLIT_PMEM_INFO_CNT) {
- DEBUG ((DEBUG_INFO, "SLIT: Found PMem %d at socket %d (mem type 0x%X)\n", Pmem, Socket, Type));
- mSlitPmemInfo[Pmem].Pmem = Pmem;
- mSlitPmemInfo[Pmem].Socket = Socket;
- mSlitPmemInfo[Pmem].Valid = TRUE;
- return;
- }
- DEBUG ((DEBUG_ERROR, "SLIT: Error - Number of PMem nodes (%d) exceed PMem info data table size (%d)\n",
- Pmem, EFI_ACPI_SLIT_PMEM_INFO_CNT));
- ASSERT (FALSE);
- }
- /**
- Retrieves socket correlated with given AEP PMEM NUMA node
- @param[in] Pmem AEP PMEM Numa node
- @retval Socket correlated with given AEP PMEM NUMA node
- **/
- UINT8
- GetSocketForPmem (
- IN UINT8 Pmem
- )
- {
- UINT8 PmemInfoEntry;
- for (PmemInfoEntry = 0; PmemInfoEntry < EFI_ACPI_SLIT_PMEM_INFO_CNT; PmemInfoEntry++) {
- if (mSlitPmemInfo[PmemInfoEntry].Valid && mSlitPmemInfo[PmemInfoEntry].Pmem == Pmem) {
- return mSlitPmemInfo[PmemInfoEntry].Socket;
- }
- }
- DEBUG ((DEBUG_ERROR, "SLIT: Error - PMem node (%d) is not associated with any socket\n", Pmem));
- ASSERT (FALSE);
- return PMEM_INVALID_SOCKET;
- }
- /**
- This function gets the physical node index for given FPGA NUMA node.
- If the given FPGA NUMA node doesn't exist, an invalid physical node
- index 0xff will be returned.
- @param[in] FpgaNumaNodeId FPGA NUMA node index (0 based).
- @retval Physical node index of given FPGA NUMA node (0 based).
- **/
- UINT8
- GetPhyNodeIdForFpga (
- IN UINT8 FpgaNumaNodeId
- )
- {
- UINT32 FpgaPresentBitMap;
- UINT8 PhyNodeId;
- PhyNodeId = 0;
- FpgaPresentBitMap = mCpuCsrAccessVarPtr->FpgaPresentBitMap;
- while ((FpgaNumaNodeId != (UINT8) -1) && (FpgaPresentBitMap != 0)) {
- if ((FpgaPresentBitMap & BIT0) != 0) {
- FpgaNumaNodeId--;
- }
- FpgaPresentBitMap >>= 1;
- PhyNodeId++;
- }
- if ((FpgaPresentBitMap == 0) && (FpgaNumaNodeId != (UINT8) -1)) {
- return (UINT8) -1;
- }
- return PhyNodeId - 1;
- }
- /**
- Retrieves number of FPGA Presents
- @retval Number of FPGA Presents in the system
- **/
- UINT8
- GetFpgaCount (
- VOID)
- {
- UINT8 FpgaCount = 0;
- UINT32 FpgaPresentBitMap = mCpuCsrAccessVarPtr->FpgaPresentBitMap;
- while (FpgaPresentBitMap) {
- if (FpgaPresentBitMap & BIT0) {
- FpgaCount++;
- }
- FpgaPresentBitMap >>= 1;
- }
- return FpgaCount;
- }
- /**
- Retrieves number of AEP PMEM NUMA nodes
- @retval Number of AEP PMEM NUMA nodes
- **/
- UINT8
- GetPmemNodeCount (
- VOID
- )
- {
- UINT8 Socket;
- UINT8 SadRule;
- UINT8 PmemNodeCount = 0;
- EFI_STATUS Status = EFI_SUCCESS;
- DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
- Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, (VOID **) &DynamicSiLibraryProtocol2);
- if (EFI_ERROR (Status)) {
- ASSERT_EFI_ERROR (Status);
- return 0;
- }
- for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
- if ((mCpuCsrAccessVarPtr->socketPresentBitMap & (BIT0 << Socket)) == 0) {
- continue;
- }
- for (SadRule = 0; SadRule < MAX_SAD_RULES; SadRule++) {
- //
- // Only local SADs of PMEM type should be taken into consideration.
- // Skip any memory region marked reserved.
- //
- if (mSystemMemoryMap->Socket[Socket].SAD[SadRule].local &&
- DynamicSiLibraryProtocol2->IsMemTypeAppDirect (mSystemMemoryMap->Socket[Socket].SAD[SadRule].type) &&
- !DynamicSiLibraryProtocol2->IsMemTypeReserved (mSystemMemoryMap->Socket[Socket].SAD[SadRule].type)) {
- SavePmemInfo (PmemNodeCount++, Socket, mSystemMemoryMap->Socket[Socket].SAD[SadRule].type);
- }
- }
- }
- return PmemNodeCount;
- }
- /**
- Retrieves number of clusters in the system if system is in SNC mode. If system is not
- in SNC mode, the return 1.
- @return Number of clusters in the system in SNC mode or 1 if system is not in SNC mode.
- **/
- UINT8
- GetNumClusters (
- VOID
- )
- {
- UINT8 NumClusters;
- NumClusters = mIioUds->IioUdsPtr->SystemStatus.OutNumOfCluster;
- if ((NumClusters == 0) || (mIioUds->IioUdsPtr->SystemStatus.OutSncEn == 0)) {
- NumClusters = 1; // For non-SNC mode, we should also return 1.
- }
- if (mSystemMemoryMap->VirtualNumaEnable) {
- NumClusters = NumClusters * mSystemMemoryMap->VirtualNumOfCluster;
- }
- return NumClusters;
- }
- /**
- Retrieves number of enabled CPUs in the system
- @param None
- @retval Number of enabled CPUs in the system
- **/
- UINT8
- GetNumCpus (
- VOID
- )
- {
- return mIioUds->IioUdsPtr->SystemStatus.numCpus;
- }
- /**
- Calculates total number of nodes
- @param[in] NumCpus Number of CPUs
- @param[in] NumClusters Number of clusters
- @param[in] PmemNodeCount Number of AEP PMEM NUMA nodes
- @retval Total number of nodes
- **/
- UINT8
- GetNodeCount (
- IN UINT8 NumCpus,
- IN UINT8 NumClusters,
- IN UINT8 PmemNodeCount,
- IN UINT8 FpgaCount
- )
- {
- UINT8 NodeCount;
- if (mSystemMemoryMap->volMemMode == VOL_MEM_MODE_MIX_1LM2LM) {
- NodeCount = ((NumCpus * NumClusters * EFI_ACPI_SLIT_DOMAINS_NODES_MAX_CNT) + PmemNodeCount + FpgaCount);
- } else {
- NodeCount = ((NumCpus * NumClusters) + PmemNodeCount + FpgaCount);
- }
- if ((NodeCount * NodeCount) < EFI_ACPI_SYSTEM_LOCALITIES_ENTRY_COUNT) {
- return NodeCount;
- }
- DEBUG ((DEBUG_ERROR, "SLIT: Error - Nodes distances info data size (%d) exceed SLIT distances info table size (%d)\n",
- (NodeCount * NodeCount), EFI_ACPI_SYSTEM_LOCALITIES_ENTRY_COUNT));
- ASSERT (FALSE);
- return 0;
- }
- /**
- Verifies whether sockets are linked
- @param[in] SourceSocket Source Socket ID
- @param[in] TargetSocket Targer Socket ID
- @retval TRUE link between source socket and target socket was found
- FALSE otherwise
- **/
- BOOLEAN
- SocketsLinked (
- IN UINT32 SourceSocket,
- IN UINT32 TargetSocket
- )
- {
- UINT8 PeerSocket;
- UINT8 LinkValid;
- UINT8 PeerSocId;
- EFI_STATUS Status = EFI_SUCCESS;
- DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
- Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, (VOID **) &DynamicSiLibraryProtocol2);
- if (EFI_ERROR (Status)) {
- ASSERT_EFI_ERROR (Status);
- return FALSE;
- }
- //
- // Validate sockets ids
- //
- if ((SourceSocket < MAX_SOCKET) && (TargetSocket < MAX_SOCKET)) {
- //
- // Do not process when source socket is the same as target socket
- //
- if (SourceSocket != TargetSocket) {
- for (PeerSocket = 0; PeerSocket < (DynamicSiLibraryProtocol2->GetKtiPortCnt()); PeerSocket++) {
- LinkValid = mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[SourceSocket].PeerInfo[PeerSocket].Valid;
- PeerSocId = mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[SourceSocket].PeerInfo[PeerSocket].PeerSocId;
- if (LinkValid && (PeerSocId == TargetSocket)) {
- //
- // Link found
- //
- return TRUE;
- }
- }
- }
- //
- // Link not found
- //
- return FALSE;
- }
- DEBUG ((DEBUG_ERROR, "SLIT: Error when checking if sockets are linked (source socket id %d, target socket id %d)\n", SourceSocket, TargetSocket));
- return FALSE;
- }
- /**
- Initializes SLIT Table entries
- @param[in,out] Table Pointer to SLIT ACPI tables
- @retval EFI_SUCCESS operation completed successfully
- **/
- EFI_STATUS
- InitEntries (
- IN OUT ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitPtr
- )
- {
- if (SlitPtr == NULL) {
- ASSERT (SlitPtr != NULL);
- return EFI_INVALID_PARAMETER;
- }
- SetMem (&SlitPtr->NumSlit[0].Entry, EFI_ACPI_SYSTEM_LOCALITIES_ENTRY_COUNT, 0xFF);
- return EFI_SUCCESS;
- }
- /**
- Processes socket nodes
- @param[in,out] Table Pointer to SLIT ACPI tables
- @param[in] NumCpus Number of CPUs
- @param[in] NumClusters Number of clusters
- @param[in] PmemNodeCount Number of AEP PMEM NUMA nodes
- @param[in] FpgaCount Number of FPGA NUMA nodes
- @param[in] NodeCount Number of all nodes
- @retval EFI_SUCCESS operation completed successfully
- **/
- EFI_STATUS
- ProcessSockets (
- IN OUT EFI_ACPI_COMMON_HEADER *Table,
- IN UINT8 NumCpus,
- IN UINT8 NumClusters,
- IN UINT8 PmemNodeCount,
- IN UINT8 FpgaCount,
- IN UINT8 NodeCount
- )
- {
- ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitAcpiTable;
- UINT16 EntryIdx;
- UINT8 SourceNode;
- UINT8 SourceSocket;
- UINT8 SourceCluster;
- UINT8 TargetSocket;
- UINT8 TargetCluster;
- UINT8 VirtualNumaFactor;
- if (NULL == Table) {
- DEBUG ((DEBUG_ERROR, "SLIT: Error in SLIT update with data about nodes on same socket\n"));
- return EFI_INVALID_PARAMETER;
- }
- VirtualNumaFactor = 1;
- if (mSystemMemoryMap->VirtualNumaEnable) {
- VirtualNumaFactor = mSystemMemoryMap->VirtualNumOfCluster;
- }
- DEBUG ((DEBUG_INFO, "SLIT: Update with data about nodes on same socket\n"));
- SlitAcpiTable = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *)Table;
- for (SourceNode = 0; SourceNode < (NodeCount - PmemNodeCount - FpgaCount) ; SourceNode++) {
- SourceSocket = SourceNode / NumClusters;
- SourceCluster = SourceNode % NumClusters;
- for (TargetSocket = 0; TargetSocket < NumCpus; TargetSocket++) {
- for (TargetCluster = 0; TargetCluster < NumClusters; TargetCluster++) {
- if (SourceSocket == TargetSocket) {
- EntryIdx = (SourceNode * (NodeCount)) + (TargetSocket * NumClusters) + TargetCluster;
- //
- // Source and target are nodes on same socket
- //
- if ((SourceCluster / VirtualNumaFactor) == (TargetCluster / VirtualNumaFactor)) {
- //
- // a) Same socket same physical cluster
- //
- SlitAcpiTable->NumSlit[EntryIdx].Entry = ZERO_HOP;
- } else {
- //
- // b) Same socket different cluster
- //
- SlitAcpiTable->NumSlit[EntryIdx].Entry = ZERO_ONE;
- }
- }
- }
- }
- }
- return EFI_SUCCESS;
- }
- /**
- Processes socket nodes
- @param[in,out] Table Pointer to SLIT ACPI tables
- @param[in] NumCpus Number of CPUs
- @param[in] NumClusters Number of clusters
- @param[in] PmemNodeCount Number of AEP PMEM NUMA nodes
- @param[in] FpgaCount Number of FPGA NUMA nodes
- @param[in] NodeCount Number of all nodes
- @retval EFI_SUCCESS operation completed successfully
- **/
- EFI_STATUS
- ProcessMixedModeSockets (
- IN OUT EFI_ACPI_COMMON_HEADER *Table,
- IN UINT8 NumCpus,
- IN UINT8 NumClusters,
- IN UINT8 PmemNodeCount,
- IN UINT8 FpgaCount,
- IN UINT8 NodeCount
- )
- {
- ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitAcpiTable;
- UINT16 EntryIdx1LM;
- UINT16 EntryIdx2LM;
- UINT8 SourceNode;
- UINT8 SourceSocket;
- UINT8 SourceCluster;
- UINT8 TargetSocket;
- UINT8 TargetCluster;
- BOOLEAN Is2LM;
- if (NULL == Table) {
- DEBUG ((DEBUG_ERROR, "SLIT: Error in SLIT update with data about nodes on same socket for Mixed Mode\n"));
- return EFI_INVALID_PARAMETER;
- }
- DEBUG ((DEBUG_INFO, "SLIT: Update with data about nodes on same socket for Mixed Mode\n"));
- SlitAcpiTable = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *)Table;
- for (SourceNode = 0; SourceNode < (NodeCount - PmemNodeCount - FpgaCount) ; SourceNode++) {
- Is2LM = (SourceNode >= NumCpus * NumClusters) ? TRUE : FALSE;
- SourceSocket = (SourceNode - NumCpus * NumClusters * (Is2LM ? 1 : 0)) / NumClusters;
- SourceCluster = (SourceNode - NumCpus * NumClusters * (Is2LM ? 1 : 0)) % NumClusters;
- TargetSocket = SourceSocket;
- for (TargetCluster = 0; TargetCluster < NumClusters; TargetCluster++) {
- EntryIdx1LM = (UINT16)((SourceNode * NodeCount) + (TargetSocket * NumClusters) + TargetCluster);
- EntryIdx2LM = EntryIdx1LM + NumCpus * NumClusters;
- if ((SourceCluster == TargetCluster) && (Is2LM == FALSE)) {
- //
- // CPU -> 1LM at the same socket, the same cluster
- //
- SlitAcpiTable->NumSlit[EntryIdx1LM].Entry = ZERO_HOP;
- //
- // CPU -> 2LM at the same socket, the same cluster
- //
- SlitAcpiTable->NumSlit[EntryIdx2LM].Entry = ZERO_ONE;
- } else if ((SourceCluster == TargetCluster) && (Is2LM == TRUE)) {
- //
- // CPU -> 2LM at the same socket, the same cluster
- //
- SlitAcpiTable->NumSlit[EntryIdx1LM].Entry = ZERO_ONE;
- //
- // not effective
- //
- SlitAcpiTable->NumSlit[EntryIdx2LM].Entry = ZERO_HOP;
- } else if ((SourceCluster != TargetCluster) && (Is2LM == FALSE)) {
- //
- // CPU -> 1LM at the same socket, different cluster
- //
- SlitAcpiTable->NumSlit[EntryIdx1LM].Entry = ZERO_ONE;
- //
- // CPU -> 2LM at the same socket, different cluster
- //
- SlitAcpiTable->NumSlit[EntryIdx2LM].Entry = ZERO_TWO;
- } else {
- //
- // branch condition: ((SourceCluster != TargetCluster) && (Is2LM == TRUE))
- // CPU -> 2LM at the same socket, different cluster
- //
- SlitAcpiTable->NumSlit[EntryIdx1LM].Entry = ZERO_TWO;
- //
- // not effective
- //
- SlitAcpiTable->NumSlit[EntryIdx2LM].Entry = ZERO_TWO;
- }
- }
- }
- return EFI_SUCCESS;
- }
- /**
- Processes connections between sockets to retrieve valid distances
- @param[in,out] Table Pointer to SLIT ACPI tables
- @param[in] NumCpus Number of CPUs
- @param[in] NumClusters Number of clusters
- @param[in] PmemNodeCount Number of AEP PMEM NUMA nodes
- @param[in] FpgaCount Number of FPGA NUMA nodes
- @param[in] NodeCount Number of all nodes
- @retval EFI_SUCCESS operation completed successfully
- **/
- EFI_STATUS
- ProcessSocketsLinks (
- IN OUT EFI_ACPI_COMMON_HEADER *Table,
- IN UINT8 NumCpus,
- IN UINT8 NumClusters,
- IN UINT8 PmemNodeCount,
- IN UINT8 FpgaCount,
- IN UINT8 NodeCount
- )
- {
- ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitAcpiTable;
- UINT8 SourceNode;
- UINT8 SourceSocket;
- UINT8 TargetSocket;
- if (NULL == Table) {
- DEBUG ((DEBUG_ERROR, "SLIT: Error in processing links between sockets\n"));
- return EFI_INVALID_PARAMETER;
- }
- DEBUG ((DEBUG_INFO, "SLIT: Update table with links between sockets\n"));
- SlitAcpiTable = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *)Table;
- for (SourceNode = 0; SourceNode < (NodeCount - PmemNodeCount - FpgaCount); SourceNode++) {
- SourceSocket = SourceNode / NumClusters;
- for (TargetSocket = 0; TargetSocket < NumCpus; TargetSocket++) {
- if (SocketsLinked (GetSocketPhysicalId (SourceSocket), GetSocketPhysicalId (TargetSocket))) {
- SetMem (&SlitAcpiTable->NumSlit[(SourceNode * NodeCount) + (TargetSocket * NumClusters)].Entry,
- NumClusters, ONE_HOP);
- }
- }
- }
- return EFI_SUCCESS;
- }
- /**
- Processes connections between sockets to retrieve valid distances
- @param[in,out] Table Pointer to SLIT ACPI tables
- @param[in] NumCpus Number of CPUs
- @param[in] NumClusters Number of clusters
- @param[in] PmemNodeCount Number of AEP PMEM NUMA nodes
- @param[in] FpgaCount Number of FPGA NUMA nodes
- @param[in] NodeCount Number of all nodes
- @retval EFI_SUCCESS operation completed successfully
- **/
- EFI_STATUS
- ProcessMixedModeSocketsLinks (
- IN OUT EFI_ACPI_COMMON_HEADER *Table,
- IN UINT8 NumCpus,
- IN UINT8 NumClusters,
- IN UINT8 PmemNodeCount,
- IN UINT8 FpgaCount,
- IN UINT8 NodeCount
- )
- {
- ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitAcpiTable;
- UINT16 EntryIdx1LM;
- UINT16 EntryIdx2LM;
- UINT8 SourceNode;
- UINT8 SourceSocket;
- UINT8 TargetSocket;
- UINT8 TargetCluster;
- BOOLEAN Is2LM;
- if (NULL == Table) {
- DEBUG ((DEBUG_ERROR, "SLIT: Error in processing links between sockets in Mixed Mode\n"));
- return EFI_INVALID_PARAMETER;
- }
- DEBUG ((DEBUG_INFO, "SLIT: Update table with links between sockets in Mixed Mode\n"));
- SlitAcpiTable = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *)Table;
- for (SourceNode = 0; SourceNode < (NodeCount - PmemNodeCount - FpgaCount); SourceNode++) {
- Is2LM = (SourceNode >= NumCpus * NumClusters) ? TRUE : FALSE;
- SourceSocket = (SourceNode - NumCpus * NumClusters * (Is2LM ? 1 : 0)) / NumClusters;
- for (TargetSocket = 0; TargetSocket < NumCpus; TargetSocket++) {
- if (SocketsLinked (GetSocketPhysicalId (SourceSocket), GetSocketPhysicalId (TargetSocket))) {
- //
- // If both sockets are linked by KTI and not the same socket.
- //
- for (TargetCluster = 0; TargetCluster < NumClusters; TargetCluster++) {
- EntryIdx1LM = (UINT16)((SourceNode * NodeCount) + (TargetSocket * NumClusters) + TargetCluster);
- EntryIdx2LM = EntryIdx1LM + NumCpus * NumClusters;
- if (Is2LM == FALSE) {
- //
- // CPU -> 1LM at different socket
- //
- SlitAcpiTable->NumSlit[EntryIdx1LM].Entry = ONE_HOP;
- //
- // CPU -> 2LM at different socket
- //
- SlitAcpiTable->NumSlit[EntryIdx2LM].Entry = ONE_ONE;
- } else {
- //
- // branch condition: (Is2LM == TRUE)
- // CPU -> 2LM at different socket
- //
- SlitAcpiTable->NumSlit[EntryIdx1LM].Entry = ONE_ONE;
- //
- // not effective
- //
- SlitAcpiTable->NumSlit[EntryIdx2LM].Entry = ONE_TWO;
- }
- }
- }
- }
- }
- return EFI_SUCCESS;
- }
- /**
- Processes all AEP PMEM NUMA nodes
- @param[in,out] Table Pointer to SLIT ACPI tables
- @param[in] NumCpus Number of CPUs
- @param[in] NumClusters Number of clusters
- @param[in] PmemNodeCount Number of AEP PMEM NUMA nodes
- @param[in] FpgaCount Number of FPGA NUMA nodes
- @param[in] NodeCount Number of all nodes
- @retval EFI_SUCCESS operation completed successfully
- **/
- EFI_STATUS
- ProcessPmems (
- IN OUT EFI_ACPI_COMMON_HEADER *Table,
- IN UINT8 NumCpus,
- IN UINT8 NumClusters,
- IN UINT8 PmemNodeCount,
- IN UINT8 FpgaCount,
- IN UINT8 NodeCount
- )
- {
- ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitAcpiTable;
- UINT16 EntryIdx;
- UINT8 SourceNode;
- UINT8 TargetNode;
- UINT8 SourceSocket;
- UINT8 TargetCluster;
- UINT8 TargetSocket;
- UINT8 SourcePmem;
- UINT8 TargetPmem;
- UINT8 SourcePmemSocket;
- UINT8 TargetPmemSocket;
- UINT8 TotalVolMemNodes;
- if (NULL == Table) {
- DEBUG ((DEBUG_ERROR, "SLIT: Error in processing PMems\n"));
- return EFI_INVALID_PARAMETER;
- }
- if (mSystemMemoryMap->volMemMode == VOL_MEM_MODE_MIX_1LM2LM) {
- TotalVolMemNodes = NumCpus * NumClusters * EFI_ACPI_SLIT_DOMAINS_NODES_MAX_CNT;
- } else {
- TotalVolMemNodes = NumCpus * NumClusters;
- }
- DEBUG ((DEBUG_INFO, "SLIT: Include PMem NUMA nodes\n"));
- if (PmemNodeCount > 0) {
- SlitAcpiTable = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *)Table;
- //
- // 1) AEP PMEM nodes to AEP PMEM nodes distances
- //
- for (SourceNode = (NodeCount - PmemNodeCount - FpgaCount); SourceNode < (NodeCount - FpgaCount); SourceNode++) {
- SourcePmem = SourceNode - TotalVolMemNodes;
- for (TargetPmem = 0; TargetPmem < PmemNodeCount; TargetPmem++) {
- TargetNode = TargetPmem + TotalVolMemNodes;
- EntryIdx = (SourceNode * NodeCount) + TargetNode;
- if (SourcePmem == TargetPmem) {
- SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_ZERO_HOP;
- } else {
- //
- // Retrieve sockets associated with PMEMs
- //
- SourcePmemSocket = GetSocketForPmem (SourcePmem);
- TargetPmemSocket = GetSocketForPmem (TargetPmem);
- if (SourcePmemSocket == TargetPmemSocket) {
- //
- // PMEMs are on the same socket
- //
- SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_ONE_ONE;
- } else {
- //
- // Assign 2 hop and process with PeerInfo checking
- //
- SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_TWO_HOP;
- //
- // Examine PeerInfo to look for link between AEP PMEM source socket and AEP PMEM target socket
- //
- if (SocketsLinked (SourcePmemSocket, TargetPmemSocket)) {
- //
- // Link found assign 1 hop
- //
- SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_ONE_HOP;
- }
- }
- }
- }
- }
- //
- // 2) Sockets to AEP PMEM nodes distances
- //
- for (SourceNode = 0; SourceNode < (NodeCount - PmemNodeCount - FpgaCount); SourceNode++) {
- SourceSocket = GetSocketPhysicalId (SourceNode / NumClusters);
- for (TargetPmem = 0; TargetPmem < PmemNodeCount; TargetPmem++) {
- TargetPmemSocket = GetSocketForPmem (TargetPmem);
- TargetNode = TargetPmem + TotalVolMemNodes;
- EntryIdx = (SourceNode * NodeCount) + TargetNode;
- if (SourceSocket == TargetPmemSocket) {
- SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_ONE_ONE;
- } else {
- //
- // Assign 2 hop and process with PeerInfo checking
- //
- SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_TWO_HOP;
- //
- // Examine PeerInfo to look for link between source socket and AEP PMEM socket
- //
- if (SocketsLinked (SourceSocket, TargetPmemSocket)) {
- //
- // Link found assign 1 hop
- //
- SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_ONE_HOP;
- }
- }
- }
- }
- //
- // 3) AEP PMEM nodes to sockets distances
- //
- for (SourceNode = (NodeCount - PmemNodeCount - FpgaCount); SourceNode < (NodeCount - FpgaCount); SourceNode++) {
- SourcePmem = SourceNode - TotalVolMemNodes;
- SourcePmemSocket = GetSocketForPmem (SourcePmem);
- for (TargetSocket = 0; TargetSocket < NumCpus; TargetSocket++) {
- for (TargetCluster = 0; TargetCluster < NumClusters; TargetCluster++) {
- EntryIdx = (SourceNode * NodeCount) + (TargetSocket * NumClusters) + TargetCluster;
- if(SourcePmemSocket == GetSocketPhysicalId (TargetSocket)) {
- SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_ONE_ONE;
- } else {
- //
- // Assign 2 hop and process with PeerInfo checking
- //
- SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_TWO_HOP;
- //
- // Examine PeerInfo to look for link between source socket and AEP PMEM socket
- //
- if (SocketsLinked (SourcePmemSocket, GetSocketPhysicalId (TargetSocket))) {
- //
- // Link found assign 1 hop
- //
- SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_ONE_HOP;
- }
- }
- }
- }
- }
- } else {
- DEBUG ((DEBUG_INFO, "SLIT: PMem NUMA nodes not present\n"));
- }
- return EFI_SUCCESS;
- }
- /**
- This function processes all FPGA NUMA nodes.
- @param[in,out] Table Pointer to SLIT ACPI tables.
- @param[in] NumClusters Number of clusters.
- @param[in] PmemNodeCount Number of AEP PMEM NUMA nodes.
- @param[in] FpgaCount Number of FPGA NUMA nodes.
- @param[in] NodeCount Number of all nodes.
- @retval EFI_SUCCESS This function is executed successfully.
- @retval EFI_INVALID_PARAMETER Some of input parameters are invalid.
- **/
- EFI_STATUS
- ProcessFpgaNodes (
- IN OUT EFI_ACPI_COMMON_HEADER *Table,
- IN UINT8 NumClusters,
- IN UINT8 PmemNodeCount,
- IN UINT8 FpgaCount,
- IN UINT8 NodeCount
- )
- {
- ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitAcpiTable;
- UINT8 SourceNode;
- UINT8 TargetNode;
- UINT8 SourceSocket;
- UINT8 TargetSocket;
- if (Table == NULL) {
- DEBUG ((DEBUG_ERROR, "SLIT: Error in processing FPGA nodes\n"));
- return EFI_INVALID_PARAMETER;
- }
- if (FpgaCount == 0) {
- return EFI_SUCCESS;
- }
- SlitAcpiTable = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *)Table;
- for (SourceNode = (NodeCount - FpgaCount); SourceNode < NodeCount; SourceNode++) {
- SourceSocket = GetPhyNodeIdForFpga (SourceNode - (NodeCount - FpgaCount));
- for (TargetNode = 0; TargetNode < NodeCount; TargetNode++) {
- if (TargetNode < (NodeCount- PmemNodeCount - FpgaCount)) {
- TargetSocket = GetSocketPhysicalId (TargetNode / NumClusters); // Normal nodes
- } else if (TargetNode < (NodeCount - FpgaCount)) {
- TargetSocket = GetSocketForPmem (TargetNode - (NodeCount - PmemNodeCount - FpgaCount)); // PMEM nodes
- } else {
- TargetSocket = GetPhyNodeIdForFpga (TargetNode - (NodeCount - FpgaCount)); // FPGA nodes
- }
- if (SourceSocket == TargetSocket) {
- SlitAcpiTable->NumSlit[SourceNode * NodeCount + TargetNode].Entry = ZERO_HOP;
- } else if (SocketsLinked (SourceSocket, TargetSocket)) {
- SlitAcpiTable->NumSlit[SourceNode * NodeCount + TargetNode].Entry = ONE_HOP;
- SlitAcpiTable->NumSlit[TargetNode * NodeCount + SourceNode].Entry = ONE_HOP;
- } else {
- SlitAcpiTable->NumSlit[SourceNode * NodeCount + TargetNode].Entry = TWO_HOP;
- SlitAcpiTable->NumSlit[TargetNode * NodeCount + SourceNode].Entry = TWO_HOP;
- }
- }
- }
- return EFI_SUCCESS;
- }
- /**
- Processes all remaining valid SLIT nodes
- @param[in,out] Table pointer to SLIT ACPI tables
- @retval EFI_SUCCESS operation completed successfully
- **/
- EFI_STATUS
- ProcessRemainingNodes (
- IN OUT EFI_ACPI_COMMON_HEADER *Table
- )
- {
- ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitAcpiTable;
- UINT16 EntryIdx = 0;
- UINT16 MaxTableEntries;
- UINT8 NodeCount;
- if (NULL == Table) {
- DEBUG ((DEBUG_ERROR, "SLIT: Error while processing remaining valid nodes\n"));
- return EFI_INVALID_PARAMETER;
- }
- DEBUG ((DEBUG_INFO, "SLIT: Fill in the rest of the SLIT table\n"));
- SlitAcpiTable = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *)Table;
- NodeCount = (UINT8)SlitAcpiTable->Header.NumberOfSystemLocalities;
- MaxTableEntries = NodeCount * NodeCount;
- while (EntryIdx < MaxTableEntries) {
- if (SlitAcpiTable->NumSlit[EntryIdx].Entry == 0xFF) {
- //
- // This entry has not been filled yet, assign 2 hop to this table entry
- //
- SlitAcpiTable->NumSlit[EntryIdx].Entry = TWO_HOP;
- }
- if ((EntryIdx % NodeCount) == 0) {
- DEBUG ((DEBUG_INFO, "[%2d - %2d] ", EntryIdx/NodeCount, EntryIdx%NodeCount));
- }
- EntryIdx++;
- }
- return EFI_SUCCESS;
- }
- /**
- Processes unused SLIT nodes
- @param[in,out] Table pointer to SLIT ACPI tables
- @retval EFI_SUCCESS operation completed successfully
- **/
- EFI_STATUS
- ProcessUnusedNodes (
- IN OUT EFI_ACPI_COMMON_HEADER *Table
- )
- {
- ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitAcpiTable;
- UINT16 MaxTableEntries;
- UINT8 NodeCount;
- if (NULL == Table) {
- DEBUG ((DEBUG_ERROR, "SLIT: Error while processing unused nodes\n"));
- return EFI_INVALID_PARAMETER;
- }
- DEBUG ((DEBUG_INFO, "SLIT: Zero out the unused nodes\n"));
- SlitAcpiTable = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *)Table;
- NodeCount = (UINT8)SlitAcpiTable->Header.NumberOfSystemLocalities;
- MaxTableEntries = NodeCount * NodeCount;
- SetMem (&SlitAcpiTable->NumSlit[MaxTableEntries],
- (UINTN)&SlitAcpiTable->NumSlit[EFI_ACPI_SYSTEM_LOCALITIES_ENTRY_COUNT] - (UINTN)&SlitAcpiTable->NumSlit[MaxTableEntries], 0);
- return EFI_SUCCESS;
- }
- /**
- Updates System Locality Distance Information Table (SLIT)
- @param[in,out] Table pointer to SLIT ACPI tables
- @retval EFI_SUCCESS operation completed successfully
- @retval EFI_ABORTED operation not completed due to processing error
- **/
- EFI_STATUS
- PatchSLitTable (
- IN OUT EFI_ACPI_COMMON_HEADER *Table
- )
- {
- ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitAcpiTable;
- EFI_STATUS Status;
- UINT8 NodeCount;
- UINT8 NumCpus;
- UINT8 NumClusters;
- UINT8 PmemNodeCount;
- UINT8 FpgaCount;
- NumCpus = GetNumCpus ();
- NumClusters = GetNumClusters ();
- PmemNodeCount = GetPmemNodeCount ();
- FpgaCount = GetFpgaCount();
- NodeCount = GetNodeCount (NumCpus, NumClusters, PmemNodeCount, FpgaCount);
- DEBUG ((DEBUG_INFO, "SLIT: NumCpus %d, NumClusters %d, PmemNodeCount %d -> NodeCount %d FpgaCount %d\n",
- NumCpus, NumClusters, PmemNodeCount, NodeCount,FpgaCount));
- SlitAcpiTable = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *)Table;
- SlitAcpiTable->Header.NumberOfSystemLocalities = NodeCount;
- //
- // 1) Initialize all entries to 0xFF
- //
- Status = InitEntries (SlitAcpiTable);
- //
- // 2) Update SLIT table with data about nodes on same socket
- //
- if (!EFI_ERROR(Status)) {
- if (mSystemMemoryMap->volMemMode == VOL_MEM_MODE_MIX_1LM2LM) {
- Status = ProcessMixedModeSockets (Table, NumCpus, NumClusters, PmemNodeCount, FpgaCount, NodeCount);
- } else {
- Status = ProcessSockets (Table, NumCpus, NumClusters, PmemNodeCount, FpgaCount, NodeCount);
- }
- }
- //
- // 3) Update table with links between sockets by examining PeerInfo structure
- //
- if (!EFI_ERROR (Status)) {
- if (mSystemMemoryMap->volMemMode == VOL_MEM_MODE_MIX_1LM2LM) {
- Status = ProcessMixedModeSocketsLinks (Table, NumCpus, NumClusters, PmemNodeCount, FpgaCount, NodeCount);
- } else {
- Status = ProcessSocketsLinks (Table, NumCpus, NumClusters, PmemNodeCount, FpgaCount, NodeCount);
- }
- }
- //
- // 4) Update table with PMEMs
- //
- if (!EFI_ERROR (Status)) {
- Status = ProcessPmems (Table, NumCpus, NumClusters, PmemNodeCount, FpgaCount, NodeCount);
- }
- //
- // 5 Update table with FPGA
- //
- if (!EFI_ERROR (Status)) {
- Status = ProcessFpgaNodes (Table, NumClusters, PmemNodeCount, FpgaCount, NodeCount);
- }
- //
- // 6) Fill in the rest of the Slit table, 2 hops between any remaining valid nodes
- //
- if (!EFI_ERROR (Status)) {
- Status = ProcessRemainingNodes (Table);
- }
- //
- // 7) Zero out the unused nodes
- //
- if (!EFI_ERROR (Status)) {
- Status = ProcessUnusedNodes (Table);
- }
- //
- // 8) Print the entire SLIT table
- //
- if (!EFI_ERROR (Status)) {
- DisplayEntries (SlitAcpiTable);
- }
- ASSERT_EFI_ERROR (Status);
- return Status;
- }
- /**
- Allocate memory and fill SLIT information to this buffer, then
- install this table to ACPI table.
- @retval EFI_SUCCESS Install table success.
- @retval EFI_OUT_OF_RESOURCES Out of memory.
- **/
- EFI_STATUS
- InstallSlitTable (
- VOID
- )
- {
- ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *Table;
- UINTN TableSize;
- UINTN TableHandle = 0;
- EFI_STATUS Status;
- TableSize = sizeof (EFI_ACPI_6_2_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_HEADER) +
- sizeof (ACPI_SYSTEM_LOCALITIES_STRUCTURE) * EFI_ACPI_SYSTEM_LOCALITIES_ENTRY_COUNT;
- Table = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *) AllocateZeroPool (TableSize);
- if (Table == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- Table->Header.Header.Signature = EFI_ACPI_6_2_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE;
- Table->Header.Header.Length = (UINT32) TableSize;
- Table->Header.Header.Revision = EFI_ACPI_6_2_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_REVISION;
- Table->Header.Header.OemRevision = EFI_ACPI_OEM_SLIT_REVISION;
- CopyMem (Table->Header.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->Header.Header.OemId));
- Table->Header.Header.OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
- Table->Header.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);
- Table->Header.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
- //
- // All node init with 0 before pass to patcher
- //
- PatchSLitTable ((EFI_ACPI_COMMON_HEADER *)&Table->Header.Header);
- //
- // Publish SLIT Structure to ACPI
- //
- Status = mAcpiTable->InstallAcpiTable (
- mAcpiTable,
- Table,
- Table->Header.Header.Length,
- &TableHandle
- );
- //
- // Free memory
- //
- if (Table != NULL) {
- FreePool (Table);
- }
- return Status;
- }
|