/** @file @copyright Copyright 1999 - 2021 Intel Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include "PciHostBridge.h" #include "PciRootBridge.h" #include #include #include #include "PciRebalance.h" /****************************************************************************** * Local definitions. ******************************************************************************/ extern CHAR16 *mAcpiAddressSpaceTypeStr[]; extern CHAR16 *mPciResourceTypeStr[]; extern EFI_IIO_UDS_PROTOCOL *mIioUds; /****************************************************************************** * Variables. ******************************************************************************/ /** * The table below is a cache with pointers to protocol instances created at * Host Bridge initialization. It also provides mapping of protocol instance * to the PCI stack. */ PCI_ROOT_BRIDGE_INSTANCE *mPciRootBridgeTable[MAX_SOCKET][MAX_LOGIC_IIO_STACK] = {0}; PCI_ROOT_BRIDGE_INSTANCE *mPciRootBridgeTableReserved[MAX_SOCKET][IIO_RESERVED_1] = {0}; /****************************************************************************** * Functions. ******************************************************************************/ /** Find socket and stack index for given PCI Root Bridge protocol pointer. @param[out] PciResConfigPtr - Buffer for the resource configuration variable. @retval EFI_SUCCESS The function completed successfully. @retval EFI_NOT_FOUND The variable was not found. @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. @retval EFI_SECURITY_VIOLATION The variable could not be retrieved due to an authentication failure. **/ EFI_STATUS PciRootBridge2SocketStack ( IN PCI_ROOT_BRIDGE_INSTANCE *RootBridgePtr, OUT UINT8 *SocketPtr, OUT UINT8 *StackPtr ) { UINT8 Socket; UINT8 Stack; if (RootBridgePtr != NULL) { for (Socket = 0; Socket < NELEMENTS(mPciRootBridgeTable); Socket++) { for (Stack = 0; Stack < NELEMENTS(mPciRootBridgeTable[Socket]); Stack++) { if (mPciRootBridgeTable[Socket][Stack] == RootBridgePtr) { if (SocketPtr != NULL) { *SocketPtr = Socket; } if (StackPtr != NULL) { *StackPtr = Stack; } return EFI_SUCCESS; } } } } return EFI_NOT_FOUND; } /** Determine the last stack for a given socket @param Socket the socket for which the last socket is desired @return the number of the last socket */ UINT8 LastStackOfSocket ( UINT8 Socket ) { UINT8 LastStack; BOOLEAN FoundEnabledStack; UINT8 Stack; ASSERT (Socket < ARRAY_SIZE(mIioUds->IioUdsPtr->PlatformData.IIO_resource)); ASSERT (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Valid); FoundEnabledStack = FALSE; LastStack = 0; for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) { if (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack)) { LastStack = Stack; FoundEnabledStack = TRUE; } } ASSERT (FoundEnabledStack); return LastStack; } /** Determine the last stack for a given socket with resources @param SocketResources - CPU_RESOURCE structure pointer that stores all resources need per stack @param Socket - Index of the Socket @param ResourceType - Type of resource that requires alignment @param LastStack - Pointer that will store the value of the last stack with resources allocated to it @param ResourceSize - Pointer that will store the sum of the requested resource type @return The last stack with resources allocated to it and the total amount of resoures requested of the type requested. */ VOID LastStackWithResources ( IN CPU_RESOURCE *SocketResources, IN UINT8 Socket, IN PCI_RESOURCE_TYPE ResourceType, OUT UINT8 *LastStack, OUT UINT64 *ResourceSize ) { UINT8 Stack; *LastStack = 0; *ResourceSize = 0; for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) { if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) { continue; } switch (ResourceType) { case TypeIo: if (SocketResources->StackRes[Stack].NumIoPortsDesired != 0) { *ResourceSize += SocketResources->StackRes[Stack].NumIoPortsDesired + 1; *LastStack = Stack; } break; case TypeMem32: if (SocketResources->StackRes[Stack].MmiolLength != 0) { *ResourceSize += SocketResources->StackRes[Stack].MmiolLength + 1; *LastStack = Stack; } break; case TypeMem64: if (SocketResources->StackRes[Stack].MmiohLength != 0) { *ResourceSize += SocketResources->StackRes[Stack].MmiohLength + 1; *LastStack = Stack; } break; default: break; } } } /** Visit all stacks in this socket and recalculate the resource ranges per stack based on resource needs from PCI/PCIe device/functions. @param SocketResources - CPU_RESOURCE structure pointer that stores all resources need per stack @param Socket - Index of the Socket @param ResourceType - type of resource that requires alignment @retval EFI_SUCCESS - Succeed. @retval EFI_OUT_OF_RESOURCES - Not enough resources to be adjusted within the socket. **/ EFI_STATUS AdjustResources ( CPU_RESOURCE *SocketResources, UINT8 Socket, UINT8 ResourceType ) { UINT8 Stack; UINT64 NewLength; CONST UINT8 LastStack = LastStackOfSocket (Socket); UINT64 PreviousLimit; BOOLEAN FirstStack = TRUE; switch (ResourceType) { case TypeIo: // Return if IoResourceNeeds is not zero which indicates a socket adjustment is needed if(SocketResources->IoResourceNeeds != 0){ return EFI_OUT_OF_RESOURCES; } for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) { if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))){ continue; } // // For the first enabled stack, use the base I/O address for the socket, otherwise // calculate the new base based off the last enabled stack // if (FirstStack) { // stackPresentBitmap doesn't cover if a valid stack was disable due to resource adjustments. // Start with valid resources for current socket SocketResources->StackRes[Stack].IoBase = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].PciResourceIoBase; FirstStack = FALSE; } else { // Check to see if the previous stack is disabled by checking for equal base and limit if (SocketResources->StackRes[Stack-1].IoBase == SocketResources->StackRes[Stack-1].IoLimit) { if (PreviousLimit % 2 == 1) { PreviousLimit += 1; } SocketResources->StackRes[Stack].IoBase = (UINT16) PreviousLimit; } else { SocketResources->StackRes[Stack].IoBase = (UINT16) PreviousLimit + 1; } } NewLength = SocketResources->StackRes[Stack].NumIoPortsDesired; // //assign the left space to the last IIO stack. Reserved for across socket resource adjustment. //make adjustments if NewLength is zero // if (Stack == LastStack) { if (NewLength != 0) { if (SocketResources->IoResourcesLeft != 0) { NewLength += SocketResources->IoResourcesLeft + 1; } } else { NewLength = SocketResources->IoResourcesLeft; } } SocketResources->StackRes[Stack].NeedIoUpdate = TRUE; SocketResources->StackRes[Stack].IoLimit = (UINT16)(SocketResources->StackRes[Stack].IoBase + NewLength); PreviousLimit = SocketResources->StackRes[Stack].IoLimit; DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].IoBase =%x newLength = %x\n",Socket,Stack,SocketResources->StackRes[Stack].IoBase,NewLength)); DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].IoLimit =%x\n",Socket,Stack,SocketResources->StackRes[Stack].IoLimit)); } break; case TypeMem32: // // Return if MmiolResourceNeeds is not zero which indicates a socket adjustment is needed // if (SocketResources->MmiolResourceNeeds != 0) { return EFI_OUT_OF_RESOURCES; } // // Visit all Stacks in this Socket and recalculate the New Mem32 Ranges per Stack // for (Stack = 0; Stack < MAX_IIO_STACK; Stack++){ if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) { continue; } // // For the first enabled stack, use the base low mmio address for the socket, otherwize // calculate the new base based off the last enabled stack // if (FirstStack) { // stackPresentBitmap doesn't cover if a valid stack was disable due to resource adjustments. // Start with valid resources for current socket SocketResources->StackRes[Stack].MmiolBase = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio32Base; FirstStack = FALSE; } else { // Check to see if the previous stack is disabled by checking for equal base and limit if (SocketResources->StackRes[Stack-1].MmiolBase == SocketResources->StackRes[Stack-1].MmiolLimit) { if (PreviousLimit % 2 == 1) { PreviousLimit += 1; } SocketResources->StackRes[Stack].MmiolBase = (UINT32) PreviousLimit; } else { SocketResources->StackRes[Stack].MmiolBase = (UINT32) PreviousLimit + 1; } } // // Verify if this Stack is the one that requires an update and calculate the new Limit // otherwise assign the new limit based on the Chunk and Extra Chunk calculation and assign the Newlength // NewLength = SocketResources->StackRes[Stack].MmiolLength; // //assign the left space to the last IIO stack. Reserved for across socket resource adjustment. //make adjustments if NewLength is zero // if (Stack == LastStack) { if (NewLength != 0) { if (SocketResources->MmiolResourcesLeft){ NewLength += SocketResources->MmiolResourcesLeft + 1; } } else { NewLength = SocketResources->MmiolResourcesLeft; } } SocketResources->StackRes[Stack].MmiolUpdate = 1; SocketResources->StackRes[Stack].MmiolLimit = (UINT32)(SocketResources->StackRes[Stack].MmiolBase + NewLength); PreviousLimit = SocketResources->StackRes[Stack].MmiolLimit; DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiolBase =%x newLength = %x\n",Socket,Stack,SocketResources->StackRes[Stack].MmiolBase,NewLength)); DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiolLimit =%x\n",Socket,Stack,SocketResources->StackRes[Stack].MmiolLimit)); } break; case TypeMem64: // Return if MmiohResourceNeeds is not zero which indicates a socket adjustment is needed if (SocketResources->MmiohResourceNeeds != 0){ return EFI_OUT_OF_RESOURCES; } // // Visit all Stacks in this Socket and recalculate the New Mem64 Ranges per Stack // for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) { if(!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))){ continue; } // // For the first enabled stack, use the base high mmio address for the socket, otherwise // calculate the new base based off the last enabled stack // if (FirstStack) { // stackPresentBitmap doesn't cover if a valid stack was disable due to resource adjustments. // Start with valid resources for current socket SocketResources->StackRes[Stack].MmiohBase = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio64Base; FirstStack = FALSE; } else { // Check to see if the previous stack is disabled by checking for equal base and limit if (SocketResources->StackRes[Stack-1].MmiohBase == SocketResources->StackRes[Stack-1].MmiohLimit) { if (PreviousLimit % 2 == 1) { PreviousLimit += 1; } SocketResources->StackRes[Stack].MmiohBase = PreviousLimit; } else { SocketResources->StackRes[Stack].MmiohBase = PreviousLimit + 1; } } // // Verify if this Stack is the one that requires an update and calculate the new Limit // otherwise assign the new limit based on the Chunk and Extra Chunk calculation and assign the Newlength // NewLength = SocketResources->StackRes[Stack].MmiohLength; // //assign the left space to the last IIO stack. Reserved for across socket resource adjustment. //make adjustments if NewLength is zero // if (Stack == LastStack) { if (NewLength != 0) { if (SocketResources->MmiohResourcesLeft) { NewLength += SocketResources->MmiohResourcesLeft + 1; } } else { NewLength = SocketResources->MmiohResourcesLeft; } } SocketResources->StackRes[Stack].MmiohUpdate = 1; SocketResources->StackRes[Stack].MmiohLimit = (SocketResources->StackRes[Stack].MmiohBase + NewLength); PreviousLimit = SocketResources->StackRes[Stack].MmiohLimit; DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiohBase =%lx newLength = %lx\n",Socket,Stack,SocketResources->StackRes[Stack].MmiohBase,NewLength)); DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiohLimit =%lx\n",Socket,Stack,SocketResources->StackRes[Stack].MmiohLimit)); } // for Stack break; default: DEBUG((DEBUG_ERROR, "[PCI] ERROR: Resource Type Unknown = %x\n", ResourceType)); break; }// switch return EFI_SUCCESS; } /** Adjust resource ratio assignment among sockets to fit the resource needs from PCI devices. @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 splitted @retval EFI_SUCCESS - Succeed. @retval EFI_OUT_OF_RESOURCES - Not enough resources to be adjusted within the socket. **/ EFI_STATUS AdjustSocketResources ( CPU_RESOURCE *SocketResources, UINT8 ResourceType, UINT8 ValidSockets ) { EFI_STATUS Status; switch(ResourceType){ case TypeIo: Status = AdjustSocketIo (SocketResources, ResourceType, ValidSockets); break; case TypeMem32: Status = AdjustSocketMmioL (SocketResources, ResourceType, ValidSockets); break; case TypeMem64: Status = AdjustSocketMmioH (SocketResources, ResourceType, ValidSockets); break; default: DEBUG((DEBUG_ERROR, "ERROR: Resource Type Unknown = %x\n",ResourceType)); Status = EFI_INVALID_PARAMETER; break; } // switch return Status; } /** Calculate current system resource map with retrieved NVRAM variable to see if stored settings were applied @param[in] SocketPciResourceData - Pointer to stored CPU resource map @retval TRUE - SYSTEM_PCI_BASE_LIMITS has been rejected and was not applied or not initialized @retval FALSE - SYSTEM_PCI_BASE_LIMITS has been applied and still has relevant data **/ BOOLEAN IsResourceMapRejected ( SYSTEM_PCI_BASE_LIMITS *SocketPciResourceData ) { UINT8 Socket; UINT8 Stack; BOOLEAN Rejected = FALSE; PCI_BASE_LIMITS *StackLimits; PCI_BASE_LIMITS *UboxStackLimits; PCI_BASE_LIMITS *SocketLimits; STACK_RES *IioUdsUboxStackLimits; STACK_RES *IioUdsStackLimits; IIO_RESOURCE_INSTANCE *IioUdsSocketLimits; if (SocketPciResourceData == NULL) { return TRUE; } for (Socket = 0; Socket < MAX_SOCKET; Socket++) { if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Valid) { IioUdsSocketLimits = &mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket]; SocketLimits = &SocketPciResourceData->Socket[Socket].SocketLimits; IioUdsUboxStackLimits = &mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[UBOX_STACK]; UboxStackLimits = &SocketPciResourceData->Socket[Socket].StackLimits[UBOX_STACK]; for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) { if (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack)) { IioUdsStackLimits = &mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack]; StackLimits = &SocketPciResourceData->Socket[Socket].StackLimits[Stack]; // // Per stack // if (Socket == 0 && Stack == 0) { // First base starts at zero, mIioUds struct reserves 4K of Io for legacy purposes if (StackLimits->Io.Base != 0) { Rejected = TRUE; } } else { if (IioUdsStackLimits->PciResourceIoBase != StackLimits->Io.Base && StackLimits->Io.Base != 0) { Rejected = TRUE; } } if (IioUdsStackLimits->PciResourceIoLimit != StackLimits->Io.Limit && StackLimits->Io.Limit != 0) { Rejected = TRUE; } PCIDEBUG ("[%d.%d] Current I/O: 0x%04X..0x%04X\n", Socket, Stack, IioUdsStackLimits->PciResourceIoBase, IioUdsStackLimits->PciResourceIoLimit); PCIDEBUG ("[%d.%d] Saved I/O: 0x%04X..0x%04X %a\n", Socket, Stack, StackLimits->Io.Base, StackLimits->Io.Limit, Rejected ? "rejected" : ""); if (IioUdsStackLimits->Mmio32Base != StackLimits->LowMmio.Base && StackLimits->LowMmio.Base != 0) { Rejected = TRUE; } if (IioUdsStackLimits->Mmio32Limit != StackLimits->LowMmio.Limit && StackLimits->LowMmio.Limit != 0) { Rejected = TRUE; } PCIDEBUG ("[%d.%d] Current MMIOL: 0x%08X..0x%08X\n", Socket, Stack, IioUdsStackLimits->Mmio32Base, IioUdsStackLimits->Mmio32Limit); PCIDEBUG ("[%d.%d] Saved MMIOL: 0x%08X..0x%08X %a\n", Socket, Stack, StackLimits->LowMmio.Base, StackLimits->LowMmio.Limit, Rejected ? "rejected" : ""); if (IioUdsStackLimits->Mmio64Base != StackLimits->HighMmio.Base && StackLimits->HighMmio.Base != 0) { Rejected = TRUE; } if (IioUdsStackLimits->Mmio64Limit != StackLimits->HighMmio.Limit && StackLimits->HighMmio.Limit != 0) { Rejected = TRUE; } PCIDEBUG ("[%d.%d] Current MMIOH: 0x%012llX..0x%012llX\n", Socket, Stack, IioUdsStackLimits->Mmio64Base, IioUdsStackLimits->Mmio64Limit); PCIDEBUG ("[%d.%d] Saved MMIOH: 0x%012llX..0x%012llX %a\n", Socket, Stack, StackLimits->HighMmio.Base, StackLimits->HighMmio.Limit, Rejected ? "rejected" : ""); } } // // Per socket // if (IioUdsSocketLimits->PciResourceIoBase != SocketLimits->Io.Base && SocketLimits->Io.Base != 0) { Rejected = TRUE; } if (IioUdsSocketLimits->PciResourceIoLimit != SocketLimits->Io.Limit && SocketLimits->Io.Limit != 0) { Rejected = TRUE; } PCIDEBUG("[%d] Current I/O: 0x%04X..0x%04X\n", Socket, IioUdsSocketLimits->PciResourceIoBase, IioUdsSocketLimits->PciResourceIoLimit); PCIDEBUG("[%d] Saved I/O: 0x%04X..0x%04X %a\n", Socket, SocketLimits->Io.Base, SocketLimits->Io.Limit, Rejected ? "rejected" : ""); if (IioUdsSocketLimits->Mmio32Base != SocketLimits->LowMmio.Base && SocketLimits->LowMmio.Base != 0) { Rejected = TRUE; } if (IioUdsSocketLimits->Mmio32Limit != SocketLimits->LowMmio.Limit && SocketLimits->LowMmio.Limit != 0) { Rejected = TRUE; } PCIDEBUG ("[%d] Current MMIOL: 0x%08X..0x%08X\n", Socket, IioUdsSocketLimits->Mmio32Base, IioUdsSocketLimits->Mmio32Limit); PCIDEBUG ("[%d] Saved MMIOL: 0x%08X..0x%08X %a\n", Socket, SocketLimits->LowMmio.Base, SocketLimits->LowMmio.Limit, Rejected ? "rejected" : ""); if (IioUdsSocketLimits->Mmio64Base != SocketLimits->HighMmio.Base && SocketLimits->HighMmio.Base != 0) { Rejected = TRUE; } if (IioUdsSocketLimits->Mmio64Limit != SocketLimits->HighMmio.Limit && SocketLimits->HighMmio.Limit != 0) { Rejected = TRUE; } PCIDEBUG ("[%d] Current MMIOH: 0x%012llX..0x%012llX\n", Socket, IioUdsSocketLimits->Mmio64Base, IioUdsSocketLimits->Mmio64Limit); PCIDEBUG ("[%d] Saved MMIOH: 0x%012llX..0x%012llX %a\n", Socket, SocketLimits->HighMmio.Base, SocketLimits->HighMmio.Limit, Rejected ? "rejected" : ""); if (IioUdsUboxStackLimits->Mmio64Base != UboxStackLimits->HighMmio.Base && UboxStackLimits->HighMmio.Base != 0) { Rejected = TRUE; } if (IioUdsUboxStackLimits->Mmio64Limit != UboxStackLimits->HighMmio.Limit && UboxStackLimits->HighMmio.Limit != 0) { Rejected = TRUE; } PCIDEBUG ("[%d] Current UBOX: 0x%08X..0x%08X\n", Socket, IioUdsUboxStackLimits->Mmio64Base, IioUdsUboxStackLimits->Mmio64Limit); PCIDEBUG ("[%d] Saved UBOX: 0x%08X..0x%08X %a\n", Socket, UboxStackLimits->HighMmio.Base, UboxStackLimits->HighMmio.Limit, Rejected ? "rejected" : ""); } } DEBUG ((DEBUG_INFO, "[PCI] Resource rebalance rejected ? %a\n", Rejected ? "TRUE" : "FALSE")); return Rejected; } /** Read SYSTEM_PCI_RESOURCE_CONFIGURATION_DATA_NAME variable from flash and verify its content. If the variable does not exist, or is not valid for current system configuration the buffer at *PciResConfigPtr is just cleared. @param[out] PciResConfigPtr - Buffer for the resource configuration variable. @retval EFI_SUCCESS The function completed successfully. @retval EFI_NOT_FOUND The variable was not found. @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. @retval EFI_SECURITY_VIOLATION The variable could not be retrieved due to an authentication failure. **/ EFI_STATUS PciHostReadResourceConfig ( OUT SYSTEM_PCI_BASE_LIMITS *PciResConfigPtr ) { UINTN VarSize; EFI_STATUS Status; UINT8 Socket; VarSize = sizeof(*PciResConfigPtr); Status = gRT->GetVariable (SYSTEM_PCI_RESOURCE_CONFIGURATION_DATA_NAME, &gEfiSocketPciResourceDataGuid, NULL, &VarSize, PciResConfigPtr); if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) { goto ErrExit; } if (Status == EFI_BUFFER_TOO_SMALL || VarSize != sizeof(*PciResConfigPtr)) { PCIDEBUG ("Got variable '%s' of unexpected size %d (expect %d) - overwrite\n", SYSTEM_PCI_RESOURCE_CONFIGURATION_DATA_NAME, VarSize, sizeof(*PciResConfigPtr)); Status = EFI_NOT_FOUND; goto ErrExit; } // // If any of the below checks fails clear the buffer and return EFI_NOT_FOUND. // Status = EFI_NOT_FOUND; if (PciResConfigPtr->MmioHBase != mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio64Base || PciResConfigPtr->MmioHLimit != mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio64Limit) { PCIDEBUG ("%s: Memory map changed (MMIOH %012llX..%012llX != %012llX..%012llX) - overwrite\n", SYSTEM_PCI_RESOURCE_CONFIGURATION_DATA_NAME, PciResConfigPtr->MmioHBase, PciResConfigPtr->MmioHLimit, mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio64Base, mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio64Limit); goto ErrExit; } if (PciResConfigPtr->MmioLBase != mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Base || PciResConfigPtr->MmioLLimit != mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Limit) { PCIDEBUG ("%s: Memory map changed (MMIOL %08X..%08X != %08X..%08X) - overwrite\n", SYSTEM_PCI_RESOURCE_CONFIGURATION_DATA_NAME, PciResConfigPtr->MmioLBase, PciResConfigPtr->MmioLLimit, mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Base, mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Limit); goto ErrExit; } if (PciResConfigPtr->IoBase != mIioUds->IioUdsPtr->PlatformData.PlatGlobalIoBase || PciResConfigPtr->IoLimit != mIioUds->IioUdsPtr->PlatformData.PlatGlobalIoLimit) { PCIDEBUG ("%s: Memory map changed (I/O %04X..%04X != %04X..%04X) - overwrite\n", SYSTEM_PCI_RESOURCE_CONFIGURATION_DATA_NAME, PciResConfigPtr->IoBase, PciResConfigPtr->IoLimit, mIioUds->IioUdsPtr->PlatformData.PlatGlobalIoBase, mIioUds->IioUdsPtr->PlatformData.PlatGlobalIoLimit); goto ErrExit; } for (Socket = 0; Socket < NELEMENTS (PciResConfigPtr->Socket); Socket++) { if (PciResConfigPtr->StackPresentBitmap[Socket] != mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap) { PCIDEBUG ("%s: Stack bitmap mismach (%04X != %04X) in socket %d - overwrite\n", SYSTEM_PCI_RESOURCE_CONFIGURATION_DATA_NAME, PciResConfigPtr->StackPresentBitmap[Socket], mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap, Socket); goto ErrExit; } } return EFI_SUCCESS; ErrExit: ZeroMem (PciResConfigPtr, sizeof(*PciResConfigPtr)); return Status; } // PciHostReadResourceConfig() /** Adjust resource ratio assignment among CPU sockets to fit the resource needs from PCI devices. Update Setup variable if there are changes from the existing ratio requests for this boot. @param[in] HostBridgeInstance - The Host Bridge Instance where the resource adjustment happens. @param[out] Result - Output parameter. Indicates whether changes have been made. **/ VOID AdjustResourceAmongRootBridges ( IN PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance, OUT SOCKET_RESOURCE_ADJUSTMENT_RESULT *Result ) { PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; LIST_ENTRY *List; CPU_RESOURCE SocketResources[MAX_SOCKET]; UINT64 SocketIoLength; UINT64 SocketMem32Length; UINT64 SocketMem64Length; UINT64 SocketIoBase; UINT64 SocketMem32Base; UINT64 SocketMem64Base; UINT64 RsvLenAtBegin; UINT64 RsvLenAtEnd; UINT64 StackLength; UINT64 NewLength; UINT64 Alignment; UINT64 Remainder; UINT8 Socket; UINT8 ValidSockets; BOOLEAN ChangedType[TypeMax]; BOOLEAN ChangedTypeOOR[TypeMax]; // Change type for out of resources UINT8 TypeIndex; UINT8 ChangedBitMap; EFI_STATUS Status; SYSTEM_PCI_BASE_LIMITS SocketPciResourceData; UINT8 Stack; UINT8 LastStack; UINT16 IoGranularity; UINT32 MmiolGranularity; UINT64 MmiohGranularity; BOOLEAN OutOfResources; UINT32 UboxMmioSize; BOOLEAN IsVirtualRootBridge; PCI_BASE_LIMITS *CurStackLimits; PCI_BASE_LIMITS *UboxStackLimits; PCI_BASE_LIMITS *CurSocketLimits; UINT32 PlatGlobalMmiolBase; UINT32 VtdBarSize; *Result = SocketResourceRatioNotChanged; SetMem (ChangedType, TypeMax, FALSE); SetMem (ChangedTypeOOR, TypeMax, FALSE); ChangedBitMap = 0; OutOfResources = FALSE; IsVirtualRootBridge = FALSE; IoGranularity = mIioUds->IioUdsPtr->PlatformData.IoGranularity; MmiolGranularity = mIioUds->IioUdsPtr->PlatformData.MmiolGranularity; MmiohGranularity = (UINT64) mIioUds->IioUdsPtr->PlatformData.MmiohGranularity.lo; MmiohGranularity |= ((UINT64)mIioUds->IioUdsPtr->PlatformData.MmiohGranularity.hi) << 32; ZeroMem (&SocketResources[0], sizeof(SocketResources)); // // Read the system resource cfg from NVRAM. If the variable does not exist, or is // not valid for current system configuration the buffer SocketPciResourceData // is just cleared. // Status = PciHostReadResourceConfig (&SocketPciResourceData); if (EFI_ERROR (Status)) { if (Status != EFI_NOT_FOUND) { ASSERT_EFI_ERROR (Status); return; } // // Variable is not initialized yet, go with empty structure. // } else if (IsResourceMapRejected (&SocketPciResourceData)) { // // If variable is already initialized, but rejected by KTI do not reboot to avoid loop. // return; } UboxMmioSize = mIioUds->IioUdsPtr->PlatformData.UboxMmioSize; PlatGlobalMmiolBase = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Base; ValidSockets = 0; for (List = HostBridgeInstance->RootBridges.ForwardLink, Socket = 0; Socket < MAX_SOCKET; Socket ++) { if (!mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Valid) { continue; } ValidSockets++; // // Calculate the length of resources available per socket // if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].PciResourceIoBase >= mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].PciResourceIoLimit) { SocketIoBase = 0; SocketIoLength = 0; } else { SocketIoBase = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].PciResourceIoBase; SocketIoLength = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].PciResourceIoLimit - mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].PciResourceIoBase; } if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio32Base >= mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio32Limit) { SocketMem32Base = 0; SocketMem32Length = 0; } else { SocketMem32Base = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio32Base; SocketMem32Length = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio32Limit - mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio32Base; // Reserve 8M for ubox mmio SocketMem32Length = SocketMem32Length - UboxMmioSize; } if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio64Base >= mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio64Limit) { SocketMem64Base = 0; SocketMem64Length = 0; } else{ SocketMem64Base = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio64Base; SocketMem64Length = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio64Limit - mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].Mmio64Base; } // Get all the resources that are in this socket SocketResources[Socket].IoResourcesLeft = (UINT16)SocketIoLength; SocketResources[Socket].MmiolResourcesLeft = (UINT32)SocketMem32Length; SocketResources[Socket].MmiohResourcesLeft = (UINT64)SocketMem64Length; LastStack = LastStackOfSocket (Socket); for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) { if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) { continue; } RootBridgeInstance = ROOT_BRIDGE_FROM_LINK (List); // // Check IO Resource // Alignment = RootBridgeInstance->ResAllocNode[TypeIo].Alignment + 1; NewLength = RootBridgeInstance->ResAllocNode[TypeIo].Length; if (IsVirtualRootBridge) { NewLength += NewLength; } // IoTrap allocates 256 byte range from GCD for common pool usage // For device to fit move to the next available alignment if ((Socket == 0) && (Stack == 0)) { NewLength += Alignment; } if (NewLength != 0) { // // At least 2KB align per KTI requirement. Add the length requested with given alignment. // If the sum is not 2KB aligned add on the remainder that would make it align. // Bump up to 4KB for root bridge requirements // Have to make sure Alignment is handled for direct address allocation // Remainder = SocketIoBase & (Alignment - 1); if (Remainder != 0) { NewLength += Alignment - Remainder; } if (NewLength % (IoGranularity * 2)) { Remainder = (IoGranularity * 2) - (NewLength % (IoGranularity * 2)); NewLength += Remainder; } // // Store length as length - 1 for handling // NewLength -= 1; // Zero StackLength if its disable or negative if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceIoBase >= mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceIoLimit) { StackLength = 0; } else { StackLength = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceIoLimit - mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceIoBase; } SocketResources[Socket].StackRes[Stack].NumIoPortsDesired = (UINT16)NewLength; // Check if new length can fit in the socket or stack if (SocketResources[Socket].IoResourcesLeft > (UINT16)NewLength) { SocketResources[Socket].IoResourcesLeft -= (UINT16)NewLength + 1; } else if (SocketResources[Socket].IoResourcesLeft == (UINT16)NewLength) { SocketResources[Socket].IoResourcesLeft -= (UINT16)NewLength; } else { // If there are resources left consume them if (SocketResources[Socket].IoResourcesLeft != 0) { NewLength = NewLength - SocketResources[Socket].IoResourcesLeft - 1; SocketResources[Socket].IoResourcesLeft = 0; } SocketResources[Socket].IoResourceNeeds += (UINT16)NewLength + 1; OutOfResources = TRUE; ChangedTypeOOR[TypeIo] = TRUE; } SocketResources[Socket].StackRes[Stack].IoAlignment = Alignment; if (NewLength > StackLength) { SocketResources[Socket].StackRes[Stack].NeedIoUpdate = TRUE; //IoResourcesLeft is UINT16 type, not 2's-complement value. if (SocketResources[Socket].IoResourcesLeft > SocketIoLength) { DEBUG ((DEBUG_ERROR, "[PCI] Out of Resources for Socket = %x Stack = %x Type = %x\n", Socket, Stack, TypeIo)); SocketResources[Socket].IoResourcesLeft = 0; } ChangedType[TypeIo] = TRUE; } SocketIoBase += SocketResources[Socket].StackRes[Stack].NumIoPortsDesired + 1; DEBUG ((DEBUG_INFO, "SocketResources[%x].IoResourceLeft = %x\n", Socket, SocketResources[Socket].IoResourcesLeft)); DEBUG ((DEBUG_INFO, "SocketResources[%x].StackRes[%x].IoAlignment = %x\n", Socket, Stack, SocketResources[Socket].StackRes[Stack].IoAlignment)); } else { SocketResources[Socket].StackRes[Stack].NumIoPortsDesired = 0; } // // Check Mmem32 resource. This Host bridge does not support separated MEM / PMEM requests, // so only count MEM requests here. // Alignment = RootBridgeInstance->ResAllocNode[TypeMem32].Alignment + 1; NewLength = RootBridgeInstance->ResAllocNode[TypeMem32].Length; // // Account for reserved regions at begin and end of the stack MMIO32 region. // RsvLenAtBegin = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceMem32Base - mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio32Base; RsvLenAtEnd = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio32Limit - mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceMem32Limit; NewLength += RsvLenAtBegin + RsvLenAtEnd; if (Alignment < RsvLenAtBegin) { Alignment = RsvLenAtBegin; } if (Alignment < RsvLenAtEnd) { Alignment = RsvLenAtEnd; } // // Always account for VT-d reserved resource ranges. // TODO: Remove when VTd BAR is included in RsvLenAtEnd. // if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].VtdBarAddress != 0) { VtdBarSize = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceMem32Limit - mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].VtdBarAddress + 1; NewLength += VtdBarSize; if (Alignment < VtdBarSize) { Alignment = VtdBarSize; } } if (IsVirtualRootBridge) { NewLength += NewLength; } // PCH Allocates reserved MMIO for Sx SMI handler use // For device to fit move to the next available alignment if ((Socket == 0) && (Stack == 0)) { NewLength += Alignment; } if (NewLength != 0) { // // At least 4MB align per KTI requirement. Add the length requested with given alignment. // If the sum is not 4MB aligned add on the remainder that would make it align. // Have to make sure Alignment is handled for direct address allocation // Remainder = SocketMem32Base & (Alignment - 1); if (Remainder != 0) { NewLength += Alignment - Remainder; } if (NewLength % MmiolGranularity) { Remainder = MmiolGranularity - (NewLength % MmiolGranularity); NewLength += Remainder; } if (Stack == LastStack) { // // Ubox address must be 8MB aligned for the base address on most processors; skip check // if uboxMmioSize is 0 (avoid divide by zero exception). // At this point the requested resource has already been calculated to be satisfied. // Add granularity padding if necessary to satisfy Ubox requirement. // if (UboxMmioSize != 0 && (SocketMem32Base + NewLength) % UboxMmioSize) { Remainder = UboxMmioSize - (NewLength % UboxMmioSize); NewLength += Remainder; } } // // Store length as length - 1 for handling // NewLength -= 1; // Zero StackLength if its disable or negative if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio32Base >= mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio32Limit) { StackLength = 0; } else { StackLength = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio32Limit - mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio32Base; } SocketResources[Socket].StackRes[Stack].MmiolLength = (UINT32)NewLength; // Check if new length can fit in the socket or stack if (SocketResources[Socket].MmiolResourcesLeft > (UINT32)NewLength) { SocketResources[Socket].MmiolResourcesLeft -= (UINT32)NewLength + 1; } else if (SocketResources[Socket].MmiolResourcesLeft == (UINT32)NewLength) { SocketResources[Socket].MmiolResourcesLeft -= (UINT32)NewLength; } else { // If there are resources left consume them if (SocketResources[Socket].MmiolResourcesLeft) { NewLength = NewLength - SocketResources[Socket].MmiolResourcesLeft - 1; SocketResources[Socket].MmiolResourcesLeft = 0; } SocketResources[Socket].MmiolResourceNeeds += (UINT32)NewLength + 1; OutOfResources = TRUE; ChangedTypeOOR[TypeMem32] = TRUE; } SocketResources[Socket].StackRes[Stack].MmiolAlignment = Alignment; if (NewLength > StackLength) { SocketResources[Socket].StackRes[Stack].MmiolUpdate = 1; //MmiolResourcesLeft is UINT32 type, not 2's-complement value. if (SocketResources[Socket].MmiolResourcesLeft > SocketMem32Length) { DEBUG ((DEBUG_ERROR, "Out of Resources for Socket = %x Stack = %x Type = %x\n", Socket, Stack, TypeMem32)); SocketResources[Socket].MmiolResourcesLeft = 0; } ChangedType[TypeMem32] = TRUE; } SocketMem32Base += SocketResources[Socket].StackRes[Stack].MmiolLength + 1; DEBUG ((DEBUG_INFO, "SocketResources[%x].MmiolResourceLeft = %x\n", Socket, SocketResources[Socket].MmiolResourcesLeft)); DEBUG ((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiolAlignment = %x\n", Socket, Stack, SocketResources[Socket].StackRes[Stack].MmiolAlignment)); } else { SocketResources[Socket].StackRes[Stack].MmiolLength = 0; } // // Check Mem64 resource. This Host bridge does not support separated MEM / PMEM requests, so only count MEM requests here. // Alignment = RootBridgeInstance->ResAllocNode[TypeMem64].Alignment + 1; NewLength = RootBridgeInstance->ResAllocNode[TypeMem64].Length; // // Account for reserved regions at begin and end of the stack MMIO32 region. // RsvLenAtBegin = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceMem64Base - mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio64Base; RsvLenAtEnd = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio64Limit - mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceMem64Limit; NewLength += RsvLenAtBegin + RsvLenAtEnd; if (Alignment < RsvLenAtBegin) { Alignment = RsvLenAtBegin; } if (Alignment < RsvLenAtEnd) { Alignment = RsvLenAtEnd; } if (IsVirtualRootBridge) { NewLength += NewLength; } if (NewLength != 0) { // // At least 1GB align per KTI requirement. Add the length requested with given alignment. // If the sum is not 1GB aligned add on the remainder that would make it align. // Have to make sure Alignment is handled for direct address allocation // Remainder = SocketMem64Base & (Alignment - 1); if (Remainder != 0) { NewLength += Alignment - Remainder; } if (NewLength % MmiohGranularity) { Remainder = MmiohGranularity - (NewLength % MmiohGranularity); NewLength += Remainder; } // // Store length as length - 1 for handling // NewLength -= 1; // Zero StackLength if it's disable or negative if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio64Base >= mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio64Limit) { StackLength = 0; } else { StackLength = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio64Limit - mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].Mmio64Base; } SocketResources[Socket].StackRes[Stack].MmiohLength = NewLength; // Check if new length can fit in the socket or stack if (SocketResources[Socket].MmiohResourcesLeft > NewLength) { SocketResources[Socket].MmiohResourcesLeft -= NewLength + 1; } else if (SocketResources[Socket].MmiohResourcesLeft == NewLength) { SocketResources[Socket].MmiohResourcesLeft -= NewLength; } else { // If there are resources left consume them if (SocketResources[Socket].MmiohResourcesLeft != 0) { NewLength = NewLength - SocketResources[Socket].MmiohResourcesLeft - 1; SocketResources[Socket].MmiohResourcesLeft = 0; } SocketResources[Socket].MmiohResourceNeeds += NewLength + 1; OutOfResources = TRUE; ChangedTypeOOR[TypeMem64] = TRUE; } SocketResources[Socket].StackRes[Stack].MmiohAlignment = Alignment; if (NewLength > StackLength) { SocketResources[Socket].StackRes[Stack].MmiohUpdate = 1; //MmiohResourcesLeft is UINT64 type, not 2's-complement value. if (SocketResources[Socket].MmiohResourcesLeft > SocketMem64Length) { DEBUG ((DEBUG_ERROR, "Out of Resources for Socket = %x Stack = %x Type = %x\n", Socket, Stack, TypeMem64)); SocketResources[Socket].MmiohResourcesLeft = 0; } ChangedType[TypeMem64] = TRUE; } SocketMem64Base += SocketResources[Socket].StackRes[Stack].MmiohLength + 1; DEBUG ((DEBUG_INFO, "SocketResources[%x].MmiohResourceLeft = %lx\n", Socket, SocketResources[Socket].MmiohResourcesLeft)); DEBUG ((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiohAlignment = %lx\n", Socket, Stack, SocketResources[Socket].StackRes[Stack].MmiohAlignment)); } else { SocketResources[Socket].StackRes[Stack].MmiohLength = 0; } List = List->ForwardLink; } // for Stack // Check and update all resource types in socket that needs adjustment for (TypeIndex = 0; TypeIndex < TypeMax; TypeIndex++) { if (ChangedType[TypeIndex]) { DEBUG ((DEBUG_INFO, "[%d] Adjust stack %s resources...\n", Socket, mPciResourceTypeStr[TypeIndex])); Status = AdjustResources (&SocketResources[Socket], Socket, TypeIndex); ChangedType[TypeIndex] = FALSE; if (Status == EFI_SUCCESS) { ChangedBitMap |= (1 << TypeIndex); } else { ChangedBitMap &= ~(1 << TypeIndex); } } } // // Account for Ubox resources to accurately calculate new alignments for the next socket // SocketMem32Base += UboxMmioSize; } // for Socket .. ASSERT (List == &HostBridgeInstance->RootBridges); // // If a socket is out of resources, try to adjusting sockets for more room. // if (OutOfResources && (MAX_SOCKET > 1) && (ValidSockets > 1)) { for (TypeIndex = 0; TypeIndex < TypeMax; TypeIndex++) { if (ChangedTypeOOR[TypeIndex]) { DEBUG ((DEBUG_INFO, "Adjust socket %s resources...\n", mPciResourceTypeStr[TypeIndex])); Status = AdjustSocketResources (SocketResources, TypeIndex, ValidSockets); if (Status == EFI_SUCCESS) { ChangedBitMap |= (1 << TypeIndex); } else { ChangedBitMap &= ~(1 << TypeIndex); } } } } else if (OutOfResources && ChangedTypeOOR[TypeMem64]){ // // Allow mmioh to be adjusted to access max available physical address range. // Status = AdjustSocketResources (SocketResources, TypeMem64, ValidSockets); if (Status == EFI_SUCCESS) { ChangedBitMap |= (1 << TypeIndex); } else { ChangedBitMap &= ~(1 << TypeIndex); } } // Update changed resource type. // OemGetResourceMapUpdate() will only update changed resource type so it is alright if data is zero. if (ChangedBitMap != 0) { for (Socket = 0; Socket < MAX_SOCKET; Socket++) { SocketPciResourceData.StackPresentBitmap[Socket] = mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap; for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) { if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) { continue; } CurStackLimits = &SocketPciResourceData.Socket[Socket].StackLimits[Stack]; // // Disable stacks that have no resources and are assigned none. // Reaching this far means the stack is valid and should be disabled if base equals limit and // length is zero. // Assigned address will be none zero at this point because CSTACK takes the first 4K in legacy // IO space. // if ((SocketResources[Socket].StackRes[Stack].NeedIoUpdate) && (SocketResources[Socket].StackRes[Stack].IoLimit - SocketResources[Socket].StackRes[Stack].IoBase == 0)) { SocketResources[Socket].StackRes[Stack].IoBase = (UINT16)(-1); SocketResources[Socket].StackRes[Stack].IoLimit = 0; } if ((SocketResources[Socket].StackRes[Stack].MmiolUpdate) && (SocketResources[Socket].StackRes[Stack].MmiolLimit - SocketResources[Socket].StackRes[Stack].MmiolBase == 0)) { SocketResources[Socket].StackRes[Stack].MmiolBase = (UINT32)(-1); SocketResources[Socket].StackRes[Stack].MmiolLimit = 0; } if ((SocketResources[Socket].StackRes[Stack].MmiohUpdate) && (SocketResources[Socket].StackRes[Stack].MmiohLimit - SocketResources[Socket].StackRes[Stack].MmiohBase == 0)) { SocketResources[Socket].StackRes[Stack].MmiohBase = (UINT64)(-1); SocketResources[Socket].StackRes[Stack].MmiohLimit = 0; } // Zero base if 4K because mIioUds struct reserves 4K of Io for legacy purposes // Remove if mIioUds first base starts at zero if (SocketResources[Socket].StackRes[Stack].IoBase == 0x1000){ SocketResources[Socket].StackRes[Stack].IoBase = 0; } if (SocketResources[Socket].StackRes[Stack].NeedIoUpdate) { CurStackLimits->Io.Base = SocketResources[Socket].StackRes[Stack].IoBase; CurStackLimits->Io.Limit = SocketResources[Socket].StackRes[Stack].IoLimit; } if (SocketResources[Socket].StackRes[Stack].MmiolUpdate) { if ((Socket == 0) && (Stack == 0)) { CurStackLimits->LowMmio.Base = PlatGlobalMmiolBase; } else { CurStackLimits->LowMmio.Base = SocketResources[Socket].StackRes[Stack].MmiolBase; } CurStackLimits->LowMmio.Limit = SocketResources[Socket].StackRes[Stack].MmiolLimit; } if (SocketResources[Socket].StackRes[Stack].MmiohUpdate) { CurStackLimits->HighMmio.Base = SocketResources[Socket].StackRes[Stack].MmiohBase; CurStackLimits->HighMmio.Limit = SocketResources[Socket].StackRes[Stack].MmiohLimit; } DEBUG((DEBUG_INFO, "\nSocketResources[%x].StackRes[%x].IoBase =%x\n",Socket,Stack,SocketResources[Socket].StackRes[Stack].IoBase)); DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].IoLimit =%x\n",Socket,Stack,SocketResources[Socket].StackRes[Stack].IoLimit)); DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiolBase =%x\n",Socket,Stack,SocketResources[Socket].StackRes[Stack].MmiolBase)); DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiolLimit =%x\n",Socket,Stack,SocketResources[Socket].StackRes[Stack].MmiolLimit)); DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiohBase =%lx\n",Socket,Stack,SocketResources[Socket].StackRes[Stack].MmiohBase)); DEBUG((DEBUG_INFO, "SocketResources[%x].StackRes[%x].MmiohLimit =%lx\n",Socket,Stack,SocketResources[Socket].StackRes[Stack].MmiohLimit)); } // for Stack // Initialize to disabled SocketResources[Socket].IoBase = (UINT16)(-1); SocketResources[Socket].IoLimit = 0; SocketResources[Socket].MmiolBase = (UINT32)(-1); SocketResources[Socket].MmiolLimit = 0; SocketResources[Socket].MmiohBase = (UINT64)(-1); SocketResources[Socket].MmiohLimit = 0; // Search backwards to find the beginning valid stack for (Stack = MAX_IIO_STACK - 1; Stack < MAX_IIO_STACK ; Stack--) { CurSocketLimits = &SocketPciResourceData.Socket[Socket].SocketLimits; if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) { continue; } if (SocketResources[Socket].StackRes[Stack].IoBase != (UINT16)(-1)) { SocketResources[Socket].IoBase = SocketResources[Socket].StackRes[Stack].IoBase; } if (SocketResources[Socket].StackRes[Stack].MmiolBase != (UINT32)(-1)) { SocketResources[Socket].MmiolBase = SocketResources[Socket].StackRes[Stack].MmiolBase; } if (SocketResources[Socket].StackRes[Stack].MmiohBase != (UINT64)(-1)) { SocketResources[Socket].MmiohBase = SocketResources[Socket].StackRes[Stack].MmiohBase; } } // for Stack // Search to find the last valid limit for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) { if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) { continue; } if (SocketResources[Socket].StackRes[Stack].IoLimit != 0) { SocketResources[Socket].IoLimit = SocketResources[Socket].StackRes[Stack].IoLimit; } if (SocketResources[Socket].StackRes[Stack].MmiolLimit) { SocketResources[Socket].MmiolLimit = SocketResources[Socket].StackRes[Stack].MmiolLimit; } if (SocketResources[Socket].StackRes[Stack].MmiohLimit) { SocketResources[Socket].MmiohLimit = SocketResources[Socket].StackRes[Stack].MmiohLimit; } } // for Stack // Update socket level resource range if (SocketResources[Socket].StackRes[0].NeedIoUpdate) { CurSocketLimits->Io.Base = SocketResources[Socket].IoBase; CurSocketLimits->Io.Limit = SocketResources[Socket].IoLimit; } if (SocketResources[Socket].StackRes[0].MmiolUpdate) { // // Apply stolen 8M for ubox mmio per socket // if (UboxMmioSize != 0) { UboxStackLimits = &SocketPciResourceData.Socket[Socket].StackLimits[UBOX_STACK]; UboxStackLimits->LowMmio.Base = SocketResources[Socket].MmiolLimit + 1; SocketResources[Socket].MmiolLimit = (UINT32)UboxStackLimits->LowMmio.Base + UboxMmioSize - 1; UboxStackLimits->LowMmio.Limit = SocketResources[Socket].MmiolLimit; } CurSocketLimits->LowMmio.Base = SocketResources[Socket].MmiolBase; CurSocketLimits->LowMmio.Limit = SocketResources[Socket].MmiolLimit; } if (SocketResources[Socket].StackRes[0].MmiohUpdate) { CurSocketLimits->HighMmio.Base = SocketResources[Socket].MmiohBase; CurSocketLimits->HighMmio.Limit = SocketResources[Socket].MmiohLimit; } DEBUG((DEBUG_INFO, "\nSocketResources[%x].UboxBase =%x\n",Socket,UboxStackLimits->LowMmio.Base)); DEBUG((DEBUG_INFO, "SocketResources[%x].UboxLimit =%x\n",Socket,UboxStackLimits->LowMmio.Limit)); DEBUG((DEBUG_INFO, "\nSocketResources[%x].IoBase =%x\n",Socket,SocketResources[Socket].IoBase)); DEBUG((DEBUG_INFO, "SocketResources[%x].IoLimit =%x\n",Socket,SocketResources[Socket].IoLimit)); DEBUG((DEBUG_INFO, "SocketResources[%x].MmiolBase =%x\n",Socket,SocketResources[Socket].MmiolBase)); DEBUG((DEBUG_INFO, "SocketResources[%x].MmiolLimit =%x\n",Socket,SocketResources[Socket].MmiolLimit)); DEBUG((DEBUG_INFO, "SocketResources[%x].MmiohBase =%lx\n",Socket,SocketResources[Socket].MmiohBase)); DEBUG((DEBUG_INFO, "SocketResources[%x].MmiohLimit =%lx\n",Socket,SocketResources[Socket].MmiohLimit)); } // for Socket SocketPciResourceData.MmioHBase = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio64Base; SocketPciResourceData.MmioHLimit = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio64Limit; SocketPciResourceData.MmioLBase = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Base; SocketPciResourceData.MmioLLimit = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Limit; SocketPciResourceData.IoBase = mIioUds->IioUdsPtr->PlatformData.PlatGlobalIoBase; SocketPciResourceData.IoLimit = mIioUds->IioUdsPtr->PlatformData.PlatGlobalIoLimit; PCIDEBUG("Writing resource rebalance request '%s':\n", SYSTEM_PCI_RESOURCE_CONFIGURATION_DATA_NAME); PCIDEBUG("System I/O : %04X..%04X\n", SocketPciResourceData.IoBase, SocketPciResourceData.IoLimit); PCIDEBUG("System MMIOL: %08X..%08X\n", SocketPciResourceData.MmioLBase, SocketPciResourceData.MmioLLimit); PCIDEBUG("System MMIOH: %012llX..%012llX\n", SocketPciResourceData.MmioHBase, SocketPciResourceData.MmioHLimit); for (Socket = 0; Socket < NELEMENTS (SocketPciResourceData.Socket); Socket++) { PCIDEBUG("[%d] StackPresent: 0x%04X\n", Socket, SocketPciResourceData.StackPresentBitmap[Socket]); PCIDEBUG("[%d] I/O : %04X..%04X\n", Socket, SocketPciResourceData.Socket[Socket].SocketLimits.Io.Base, SocketPciResourceData.Socket[Socket].SocketLimits.Io.Limit); PCIDEBUG("[%d] MMIOL: %08X..%08X\n", Socket, SocketPciResourceData.Socket[Socket].SocketLimits.LowMmio.Base, SocketPciResourceData.Socket[Socket].SocketLimits.LowMmio.Limit); PCIDEBUG("[%d] MMIOH: %012llX..%012llX\n", Socket, SocketPciResourceData.Socket[Socket].SocketLimits.HighMmio.Base, SocketPciResourceData.Socket[Socket].SocketLimits.HighMmio.Limit); for (Stack = 0; Stack < NELEMENTS (SocketPciResourceData.Socket[Socket].StackLimits); Stack++) { PCIDEBUG("[%d.%d] I/O : %04X..%04X\n", Socket, Stack, SocketPciResourceData.Socket[Socket].StackLimits[Stack].Io.Base, SocketPciResourceData.Socket[Socket].StackLimits[Stack].Io.Limit); PCIDEBUG("[%d.%d] MMIOL: %08X..%08X\n", Socket, Stack, SocketPciResourceData.Socket[Socket].StackLimits[Stack].LowMmio.Base, SocketPciResourceData.Socket[Socket].StackLimits[Stack].LowMmio.Limit); PCIDEBUG("[%d.%d] MMIOH: %012llX..%012llX\n", Socket, Stack, SocketPciResourceData.Socket[Socket].StackLimits[Stack].HighMmio.Base, SocketPciResourceData.Socket[Socket].StackLimits[Stack].HighMmio.Limit); } } *Result = SocketResourceRatioChanged; Status = gRT->SetVariable( SYSTEM_PCI_RESOURCE_CONFIGURATION_DATA_NAME, &gEfiSocketPciResourceDataGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, sizeof(SocketPciResourceData), &SocketPciResourceData ); ASSERT_EFI_ERROR(Status); } return; }