123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- /** @file
- @copyright
- Copyright 1999 - 2021 Intel Corporation. <BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <Guid/SocketPciResourceData.h>
- #include <Guid/SocketIioVariable.h>
- #include <Protocol/IioUds.h>
- #include "PciHostBridge.h"
- #include "PciRootBridge.h"
- #include "PciRebalance.h"
- extern EFI_IIO_UDS_PROTOCOL *mIioUds;
- /**
- Return TRUE if the specified socket/stack combination exists,
- otherwise return FALSE
- @param Socket - the socket to be checked
- @param Stack - the stack of the socket to be checked
- @retval TRUE - the socket/stack combination exists
- @retval FALSE - the socket/stack combination does not exist
- */
- STATIC BOOLEAN
- IsStackPresent (
- UINT8 Socket,
- UINT8 Stack
- )
- {
- BOOLEAN Result;
- UINT64 Mask;
- ASSERT (Socket < ARRAY_SIZE (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo)); // simple overrun check
- if (Socket >= ARRAY_SIZE (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo)) {
- Result = FALSE;
- goto err_exit;
- }
- //
- // if the StackPresentBitmap is a single byte, then we can track 8 stacks,
- // the sizeof will tell us how many bytes we have, we scale by 8 to
- // determine the maximum number of stacks we can track. Stacks larger
- // than this are not present essentially by definition, but could also
- // be a sign that we need a wider type to store the information; hence we
- // assert
- //
- ASSERT (Stack < 8 * sizeof(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[0].stackPresentBitmap));
- if (Stack >= 8 * sizeof(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[0].stackPresentBitmap)) {
- Result = FALSE;
- goto err_exit;
- }
- Mask = 1;
- Mask <<= Stack;
- Result = (Mask & mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap) != 0;
- err_exit:
- return Result;
- }
- /**
- Adjust resource assignment among sockets to fit the IO
- resources from the PCI() devices in the system
- @param SocketResources - CPU_RESOURCE structure pointer that stores all resources need per socket
- @param ResourceType - type of resource that requires alignment
- @param ValidSockets - Number of Valid Sockets, need it
- to calculate how resources need to
- be split
- @retval EFI_SUCCESS - Succeed.
- @retval EFI_OUT_OF_RESOURCES - Not enough resources to be adjusted within the socket.
- **/
- EFI_STATUS
- AdjustSocketIo (
- CPU_RESOURCE *SocketResources,
- UINT8 ResourceType,
- UINT8 ValidSockets
- )
- {
- UINT64 Base; ///< Next base I/O port number to use
- UINT64 Limit; ///< Most recent limit for I/O port numbers
- CONST UINT64 MaxLimit = ((UINT64)1 << 16) - 1; ///< Maximum value for limit; used to ensure we don't overflow
- CPU_RESOURCE *CurSocketResources; ///< Pointer to the CPU_RESOURE structure for the CPU we
- ///< are examining
- STACK_RESOURCE *CurStackResources; ///< Pointer to the STACK_RESOURCE structure for the CPU/Stack
- ///< we are examining
- UINT16 NumFreePorts; ///< Number of i/o ports allocated to sockets that are not used
- UINT8 LastStack; ///< Last enabled stack of the last enabled socket
- CONST UINT8 LastSocketIndex = ValidSockets - 1; ///< Index of the last socket
- UINT64 TotalResourceSize;
- UINT64 ResourceSize;
- UINT8 Socket; ///< Loop variable used to iterate over the sockets
- UINT8 Stack; ///< Loop variable used to iterate over the stacks of a given socket
- NumFreePorts = 0;
- for (Socket = 0; Socket < ValidSockets; Socket++) {
- CurSocketResources = &SocketResources[Socket];
- if (CurSocketResources->IoResourceNeeds == 0 && CurSocketResources->IoResourcesLeft != 0) {
- ASSERT (NumFreePorts < NumFreePorts + CurSocketResources->IoResourcesLeft + 1); // check for overflow
- NumFreePorts += CurSocketResources->IoResourcesLeft + 1;
- CurSocketResources->IoResourcesLeft = 0;
- }
- }
- for (Socket = 0; Socket < ValidSockets; Socket++) {
- CurSocketResources = &SocketResources[Socket];
- if (CurSocketResources->IoResourceNeeds != 0 && NumFreePorts >= CurSocketResources->IoResourceNeeds) {
- ASSERT (NumFreePorts > NumFreePorts - CurSocketResources->IoResourceNeeds); // check for underflow
- NumFreePorts -= CurSocketResources->IoResourceNeeds;
- CurSocketResources->IoResourceNeeds = 0;
- }
- }
- LastStack = LastStackOfSocket (LastSocketIndex);
- if (NumFreePorts > 0) {
- CurStackResources = &SocketResources[LastSocketIndex].StackRes[LastStack];
- if (CurStackResources->NumIoPortsDesired != 0) {
- CurStackResources->NumIoPortsDesired += NumFreePorts;
- } else {
- CurStackResources->NumIoPortsDesired += NumFreePorts - 1;
- }
- }
- //
- // Verify all resource requested can fit into the systems address range.
- //
- TotalResourceSize = 0;
- for (Socket = 0; Socket < ValidSockets; Socket ++) {
- LastStackWithResources (&SocketResources[Socket], Socket, ResourceType, &LastStack, &ResourceSize);
- TotalResourceSize += ResourceSize;
- }
- DEBUG ((DEBUG_INFO, "Total Request IO Range = %xh\n", TotalResourceSize));
- DEBUG ((DEBUG_INFO, "Total System IO Range = %xh\n", MaxLimit));
- if (TotalResourceSize > MaxLimit) {
- //
- // Not enough system resources to support the request.
- // Remove all request to update NVRAM variable for this resource type.
- //
- for (Socket = 0; Socket < ValidSockets; Socket ++) {
- for (Stack = 0; Stack < MAX_IIO_STACK; Stack ++) {
- if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) {
- continue;
- }
- SocketResources[Socket].StackRes[Stack].NeedIoUpdate = 0;
- }
- }
- DEBUG ((DEBUG_ERROR, "ERROR: Out of adjustable IO resources. Can't adjust across sockets\n"));
- return EFI_OUT_OF_RESOURCES;
- }
- DEBUG((DEBUG_ERROR, "Assigning new socket i/o range...\n"));
- Base = mIioUds->IioUdsPtr->PlatformData.IIO_resource[0].PciResourceIoBase;
- Limit = Base; // assume no resources are allocated
- for (Socket = 0, CurSocketResources = SocketResources; Socket < ValidSockets; Socket++, CurSocketResources++) {
- DEBUG ((DEBUG_INFO, "socket = %d, Base = %x, Limit =%x, MaxLimit = %x\n", Socket, Base, Limit, MaxLimit));
- ASSERT (Base < MaxLimit);
- CurSocketResources->IoBase = (UINT16)Base;
- DEBUG ((DEBUG_INFO, "set socket io base to %x\n", Base));
- for (Stack = 0, CurStackResources = CurSocketResources->StackRes;
- Stack < MAX_IIO_STACK;
- Stack++, CurStackResources++) {
- if (!IsStackPresent (Socket, Stack)) {
- DEBUG ((DEBUG_INFO, " Stack %d not present, setting base/limit to 0xffff/0\n", Stack));
- CurStackResources->IoBase = 0xffff;
- CurStackResources->IoLimit = 0;
- continue;
- }
- if (CurStackResources->NumIoPortsDesired == 0) {
- DEBUG ((DEBUG_INFO, " Stack %d doesn't need i/o resources, setting base/limit to 0xffff/0\n", Stack));
- CurStackResources->IoBase = 0xffff;
- CurStackResources->IoLimit = 0;
- CurStackResources->NeedIoUpdate = TRUE;
- continue;
- }
- DEBUG((DEBUG_INFO, " Stack %d setting i/o base to %x, ports desired was %x\n",
- Stack, Base, CurStackResources->NumIoPortsDesired));
- ASSERT (Base < MaxLimit);
- CurStackResources->IoBase = (UINT16)Base;
- Limit = Base + CurStackResources->NumIoPortsDesired;
- DEBUG ((DEBUG_INFO, " limit set to %x (var and stack)\n", Limit));
- ASSERT (Base <= Limit);
- ASSERT (Limit <= MaxLimit);
- CurStackResources->IoLimit = (UINT16)Limit;
- CurStackResources->NeedIoUpdate = TRUE;
- Base = Limit + 1;
- DEBUG ((DEBUG_INFO, " Base variable updated to %x\n", Base));
- }
- ASSERT (Limit <= MaxLimit);
- DEBUG ((DEBUG_INFO, " Socket %d limit set to %x\n", Socket, Limit));
- CurSocketResources->IoLimit = (UINT16)Limit;
- }
- DEBUG ((DEBUG_INFO, "Dumping new I/O requests\n"));
- for (Socket = 0, CurSocketResources = SocketResources; Socket < ValidSockets; Socket++, CurSocketResources++) {
- DEBUG((DEBUG_INFO, "socket %d %x/%x\n", Socket, CurSocketResources->IoBase, CurSocketResources->IoLimit));
- for (Stack = 0, CurStackResources = CurSocketResources->StackRes;
- Stack < MAX_IIO_STACK;
- Stack++, CurStackResources++) {
- DEBUG ((DEBUG_INFO, "%d/%d: %x/%x\n", Socket, Stack, CurStackResources->IoBase, CurStackResources->IoLimit));
- }
- }
- return EFI_SUCCESS;
- }
|