PciRebalanceMmio64.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /** @file
  2. @copyright
  3. Copyright 1999 - 2021 Intel Corporation. <BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <Guid/SocketPciResourceData.h>
  7. #include <Guid/SocketIioVariable.h>
  8. #include <Protocol/IioUds.h>
  9. #include "PciHostBridge.h"
  10. #include "PciRootBridge.h"
  11. #include "PciRebalance.h"
  12. extern EFI_IIO_UDS_PROTOCOL *mIioUds;
  13. /**
  14. Adjust resource assignments among sockets to fit the high
  15. MMIO resources (64-bit addresses, typically above 4GB) from
  16. the PCI(e) devices in the system
  17. @param[in,out] SocketResources - CPU_RESOURCE structure pointer that stores all resources need per socket
  18. @param[in] ResourceType - Type of resource that requires alignment
  19. @param[in] ValidSockets - Number of Valid Sockets, need it to calculate how resources need to be splitted
  20. @retval EFI_SUCCESS - Succeed.
  21. @retval EFI_OUT_OF_RESOURCES - Not enough resources to be adjusted within the socket.
  22. */
  23. EFI_STATUS
  24. AdjustSocketMmioH (
  25. IN OUT CPU_RESOURCE *SocketResources,
  26. IN UINT8 ResourceType,
  27. IN UINT8 ValidSockets
  28. )
  29. {
  30. CONST UINT8 LastSocket = ValidSockets - 1;
  31. UINT8 Socket;
  32. UINT8 Stack;
  33. UINT8 LastStack;
  34. UINT64 Take;
  35. UINT32 UboxMmioSize;
  36. UINT64 UnAllocatedMmioh;
  37. UINT64 MaxMmioh;
  38. UINT64 ResourceSize;
  39. UINT64 TotalResourceSize;
  40. UINT64 TempMmioBase;
  41. UINT64 TempMmioLimit;
  42. Take = 0;
  43. UboxMmioSize = mIioUds->IioUdsPtr->PlatformData.UboxMmioSize;
  44. UnAllocatedMmioh = 0;
  45. //
  46. // Get first and last IO base address
  47. //
  48. TempMmioBase = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio64Base;
  49. TempMmioLimit = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio64Limit;
  50. // Find all the extra space left
  51. for (Socket = 0; Socket < ValidSockets; Socket ++) {
  52. if ((SocketResources[Socket].MmiohResourceNeeds == 0) && (SocketResources[Socket].MmiohResourcesLeft != 0)) {
  53. Take += SocketResources[Socket].MmiohResourcesLeft + 1;
  54. SocketResources[Socket].MmiohResourcesLeft = 0;
  55. }
  56. }
  57. MaxMmioh = (UINT64) mIioUds->IioUdsPtr->PlatformData.MmiohGranularity.lo;
  58. MaxMmioh |= ((UINT64) mIioUds->IioUdsPtr->PlatformData.MmiohGranularity.hi) << 32;
  59. //
  60. // Maximum chunk accessible in the system based on the given granularity
  61. //
  62. if (UboxMmioSize == 0) {
  63. MaxMmioh = MaxMmioh * 32; //for 14nm
  64. } else {
  65. MaxMmioh = ((UINT64) 1 << mIioUds->IioUdsPtr->PlatformData.MaxAddressBits);
  66. }
  67. //
  68. // Find out how much MMIOH has not been allocated
  69. //
  70. if (MaxMmioh > (TempMmioLimit - TempMmioBase)) {
  71. UnAllocatedMmioh = MaxMmioh - (TempMmioLimit - TempMmioBase) - 1;
  72. } else {
  73. //
  74. // Extra MMIOH is not enough to close the gap for a successful adjustment.
  75. // Use all extra MMIOH in case if only a small amount is needed for adjustment or
  76. // the granularity was reduced due to MMIOH base.
  77. // (14nm only) or remove if map is rejected for this case to start over with correct values.
  78. // (10nm only) does not have this problem and doesn't need the code below because the limit is removed and we can use max address lines.
  79. //
  80. Take += MaxMmioh;
  81. }
  82. // Give space to sockets that needs more space favoring first come first served
  83. for (Socket = 0; Socket < ValidSockets; Socket ++) {
  84. if ((SocketResources[Socket].MmiohResourceNeeds != 0) && (Take >= SocketResources[Socket].MmiohResourceNeeds)) {
  85. //
  86. // The socket requesting additional resources can be granted by using the already
  87. // allocated range given to the whole system originally.
  88. //
  89. Take -= SocketResources[Socket].MmiohResourceNeeds;
  90. DEBUG ((DEBUG_ERROR, "SocketResources[%x].MmiohResourceNeeds = %llX\n",Socket, SocketResources[Socket].MmiohResourceNeeds));
  91. SocketResources[Socket].MmiohResourceNeeds = 0;
  92. } else if ((SocketResources[Socket].MmiohResourceNeeds != 0) &&
  93. (Take < SocketResources[Socket].MmiohResourceNeeds) &&
  94. ((UnAllocatedMmioh + Take) >= SocketResources[Socket].MmiohResourceNeeds)) {
  95. //
  96. // Apply unallocated Mmioh to the socket that requires more to satisfy its request
  97. // that's outside the allocated range given to the whole system originally.
  98. //
  99. SocketResources[Socket].MmiohResourceNeeds -= Take;
  100. UnAllocatedMmioh -= SocketResources[Socket].MmiohResourceNeeds;
  101. DEBUG ((DEBUG_INFO, "SocketResources[%x].MmiohResourceNeeds = %llX\n", Socket, SocketResources[Socket].MmiohResourceNeeds));
  102. DEBUG ((DEBUG_INFO, "Unallocated MMIOH left = %llX\n", UnAllocatedMmioh));
  103. SocketResources[Socket].MmiohResourceNeeds = 0;
  104. }
  105. }
  106. //
  107. // Give away leftover resources
  108. //
  109. LastStack = LastStackOfSocket (LastSocket);
  110. if (Take != 0) {
  111. if (SocketResources[LastSocket].StackRes[LastStack].MmiohLength != 0) {
  112. SocketResources[LastSocket].StackRes[LastStack].MmiohLength += Take;
  113. } else{
  114. SocketResources[LastSocket].StackRes[LastStack].MmiohLength += (Take - 1);
  115. }
  116. }
  117. //
  118. // Verify all resource requested can fit into the systems address range.
  119. //
  120. TotalResourceSize = 0;
  121. for (Socket = 0; Socket < ValidSockets; Socket++) {
  122. LastStackWithResources (&SocketResources[Socket], Socket, ResourceType, &LastStack, &ResourceSize);
  123. TotalResourceSize += ResourceSize;
  124. }
  125. DEBUG ((DEBUG_INFO, "MaxMmioh = %016llXh\n", MaxMmioh));
  126. DEBUG ((DEBUG_INFO, "Total Request MMIOH Range= %016llXh\n", TotalResourceSize));
  127. DEBUG ((DEBUG_INFO, "Total System MMIOH Range = %016llXh\n", (MaxMmioh - TempMmioBase)));
  128. if (TotalResourceSize > MaxMmioh) {
  129. //
  130. // Not enough system resources to support the request.
  131. // Remove all request to update NVRAM variable for this resource type.
  132. //
  133. for (Socket = 0; Socket < ValidSockets; Socket ++) {
  134. for (Stack = 0; Stack < MAX_IIO_STACK; Stack ++) {
  135. if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) {
  136. continue;
  137. }
  138. SocketResources[Socket].StackRes[Stack].MmiohUpdate = 0;
  139. }
  140. }
  141. DEBUG ((DEBUG_ERROR, "[PCI] ERROR: Out of adjustable MMIOH resources. Can't adjust across sockets\n"));
  142. return EFI_OUT_OF_RESOURCES;
  143. }
  144. DEBUG ((DEBUG_ERROR, "Assigning new socket MMIOH range...\n"));
  145. for (Socket = 0, TempMmioLimit = TempMmioBase - 1; Socket < ValidSockets; Socket++) {
  146. SocketResources[Socket].MmiohBase = TempMmioLimit + 1;
  147. //
  148. // Update the stacks base and limit values.
  149. //
  150. for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
  151. if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) {
  152. SocketResources[Socket].StackRes[Stack].MmiohBase = 0;
  153. SocketResources[Socket].StackRes[Stack].MmiohLimit = 0;
  154. } else {
  155. SocketResources[Socket].StackRes[Stack].MmiohBase = TempMmioLimit + 1;
  156. if (SocketResources[Socket].StackRes[Stack].MmiohLength != 0) {
  157. //
  158. // MmiohLength is actually length-1, so we should move TempMmioLimit by MmiohLength+1,
  159. // but only when it is >0, i.e. only for stack that has resources.
  160. //
  161. TempMmioLimit += SocketResources[Socket].StackRes[Stack].MmiohLength + 1;
  162. SocketResources[Socket].StackRes[Stack].MmiohLimit = TempMmioLimit;
  163. } else {
  164. SocketResources[Socket].StackRes[Stack].MmiohLimit = SocketResources[Socket].StackRes[Stack].MmiohBase;
  165. }
  166. SocketResources[Socket].StackRes[Stack].MmiohUpdate = 1;
  167. }
  168. DEBUG ((DEBUG_ERROR, "SocketResources[%x].StackRes[%x].MmiohBase = %llX newLength = %llX\n", Socket, Stack,
  169. SocketResources[Socket].StackRes[Stack].MmiohBase, SocketResources[Socket].StackRes[Stack].MmiohLength));
  170. DEBUG ((DEBUG_ERROR, "SocketResources[%x].StackRes[%x].MmiohLimit = %llX\n", Socket, Stack,
  171. SocketResources[Socket].StackRes[Stack].MmiohLimit));
  172. DEBUG ((DEBUG_ERROR, "SocketResources[%x].StackRes[%x].MmiohUpdate= %d\n", Socket, Stack,
  173. SocketResources[Socket].StackRes[Stack].MmiohUpdate));
  174. } // for (Stack...)
  175. SocketResources[Socket].MmiohLimit = TempMmioLimit;
  176. } // for (Socket...)
  177. return EFI_SUCCESS;
  178. }