123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- /** @file
- Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "AcpiPlatform.h"
- #define MAX_NODES_PER_SOCKET 4
- #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,
- };
- VOID
- ComputeCoordinatesForNode (
- UINTN Node,
- UINTN *X,
- UINTN *Y
- )
- {
- switch (Node) {
- case 0:
- *X = 0;
- *Y = 0;
- break;
- case 1:
- *X = 1;
- *Y = 0;
- break;
- case 2:
- *X = 0;
- *Y = 1;
- break;
- case 3:
- *X = 1;
- *Y = 1;
- break;
- default:
- *X = 0;
- *Y = 0;
- break;
- }
- }
- /**
- Compute the distance between between two nodes on socket.
- **/
- UINT8
- ComputeSlitDistanceOnSocket (
- UINTN Node1,
- UINTN Node2
- )
- {
- UINTN X1, Y1, X2, Y2;
- UINTN XDistance, YDistance;
- ComputeCoordinatesForNode (Node1, &X1, &Y1);
- ComputeCoordinatesForNode (Node2, &X2, &Y2);
- XDistance = ABS ((INTN)(X1 - X2));
- YDistance = ABS ((INTN)(Y1 - Y2));
- return (UINT8)(XDistance + YDistance + SELF_DISTANCE);
- }
- /**
- Compute the distance between between two nodes on
- different sockets.
- Node1 - local socket node number
- Node2 - remote socket node number
- **/
- UINT8
- ComputeSlitDistanceOnRemoteSocket (
- UINTN LocalNode,
- UINTN RemoteNode
- )
- {
- UINTN LocalDistance, RemoteDistance;
- //
- // Mesh forwards traffic between sockets over both CCIX links when going from
- // one quadrant to another. For example, memory access from Node 0 to Node 4
- // results in traffic being split between RCA0 and 1. Hence distance is
- // different only between upper half and lower half of sockets and not
- // between quadrants. Hemisphere configuration is not impacted as there
- // is no upper-half.
- //
- LocalDistance = 0;
- RemoteDistance = 0;
- if (LocalNode >= (MAX_NODES_PER_SOCKET / 2)) {
- LocalDistance = 1;
- }
- if (RemoteNode >= (MAX_NODES_PER_SOCKET / 2)) {
- RemoteDistance = 1;
- }
- return (UINT8)(LocalDistance + RemoteDistance + REMOTE_DISTANCE);
- }
- UINT8
- ComputeSlitDistance (
- UINTN Node1,
- UINTN Node2,
- UINTN DomainsPerSocket
- )
- {
- UINT8 Distance;
- Distance = 0;
- if ((Node1 / DomainsPerSocket) == (Node2 / DomainsPerSocket)) {
- Distance = ComputeSlitDistanceOnSocket (
- Node1 % DomainsPerSocket,
- Node2 % DomainsPerSocket
- );
- } else {
- Distance = ComputeSlitDistanceOnRemoteSocket (
- Node1 % DomainsPerSocket,
- Node2 % DomainsPerSocket
- );
- }
- return Distance;
- }
- 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;
- Status = gBS->LocateProtocol (
- &gEfiAcpiTableProtocolGuid,
- NULL,
- (VOID **)&AcpiTableProtocol
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- NumDomainPerSocket = CpuGetNumberOfSubNumaRegion ();
- NumDomain = NumDomainPerSocket * GetNumberOfActiveSockets ();
- 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++) {
- *TmpPtr = ComputeSlitDistance (Count, Count1, NumDomainPerSocket);
- }
- }
- SlitTablePointer->Header.Length = sizeof (SLITTableHeaderTemplate) + NumDomain * NumDomain;
- AcpiUpdateChecksum ((UINT8 *)SlitTablePointer, SlitTablePointer->Header.Length);
- Status = AcpiTableProtocol->InstallAcpiTable (
- AcpiTableProtocol,
- (VOID *)SlitTablePointer,
- SlitTablePointer->Header.Length,
- &SlitTableKey
- );
- FreePool ((VOID *)SlitTablePointer);
- return Status;
- }
|