AcpiPlatformLibHmat.c 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710
  1. /** @file
  2. ACPI Platform Library HMAT
  3. @copyright
  4. Copyright 2016 - 2020 Intel Corporation. <BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. //
  8. // Statements that include other files
  9. //
  10. #include "AcpiPlatformLibLocal.h"
  11. #include <Library/MemTypeLib.h>
  12. #include <Protocol/Smbios.h>
  13. #include <IndustryStandard/SmBios.h>
  14. //
  15. // The represented latency/bandwidth in 'System Locality Latency and Bandwidth
  16. // Information Structure' is expressed in multiples of Entry Base Unit.
  17. // Unit of latency is picoseconds and bandwidth is megabytes per second
  18. // Below #defines are be base units and values for calcualting the latency/bandwidth
  19. // For example: read latency of DDRT is 180ns which is 180000 picoseconds.
  20. // This is expressed as DDRT_LATENCY_BASE_UNIT of 1000 and DDRT_READ_LATENCY of 180
  21. //
  22. #define MEMORY_LATENCY_BASE_UNIT 100
  23. #define MEMORY_BANDWIDTH_BASE_UNIT 1
  24. #define DDR2LMCACHE_LATENCY_BASE_UNIT 100
  25. #define DDR2LMCACHE_BANDWIDTH_BASE_UNIT 1
  26. #define XSOCKET_LATENCY_BASE_UNIT 100
  27. #define XSOCKET_BANDWIDTH_BASE_UNIT 1
  28. //
  29. // DDRT values
  30. //
  31. #define DDRT_ACCESS_LATENCY 0
  32. #define DDRT_1LM_READ_LATENCY 2535
  33. #define DDRT_2LM_READ_LATENCY 3285
  34. #define DDRT_1LM_WRITE_LATENCY 2535
  35. #define DDRT_2LM_WRITE_LATENCY 3285
  36. #define DDRT_ACCESS_BANDWIDTH 0
  37. #define DDRT_1LM_READ_BANDWIDTH 4625
  38. #define DDRT_2LM_READ_BANDWIDTH 4625
  39. #define DDRT_1LM_WRITE_BANDWIDTH 1375
  40. #define DDRT_2LM_WRITE_BANDWIDTH 1375
  41. //
  42. // X-SOCKET values
  43. //
  44. #define XSOCKET_DDRT_1LM_ACCESS_LATENCY 0
  45. #define XSOCKET_DDRT_1LM_READ_LATENCY 3160
  46. #define XSOCKET_DDRT_1LM_WRITE_LATENCY 3160
  47. #define XSOCKET_DDRT_1LM_ACCESS_BANDWIDTH 0
  48. #define XSOCKET_DDRT_1LM_READ_BANDWIDTH 4625
  49. #define XSOCKET_DDRT_1LM_WRITE_BANDWIDTH 1375
  50. #define XSOCKET_DDRT_2LM_ACCESS_LATENCY 0
  51. #define XSOCKET_DDRT_2LM_READ_LATENCY 3885
  52. #define XSOCKET_DDRT_2LM_WRITE_LATENCY 3885
  53. #define XSOCKET_DDRT_2LM_ACCESS_BANDWIDTH 0
  54. #define XSOCKET_DDRT_2LM_READ_BANDWIDTH 4625
  55. #define XSOCKET_DDRT_2LM_WRITE_BANDWIDTH 1375
  56. //
  57. // DDR values 1LM or flat mode
  58. //
  59. #define DDR_ACCESS_LATENCY 0
  60. #define DDR_READ_LATENCY 760
  61. #define DDR_WRITE_LATENCY 760
  62. #define DDR_ACCESS_BANDWIDTH 0
  63. #define DDR_READ_BANDWIDTH 17900
  64. #define DDR_WRITE_BANDWIDTH 19100
  65. //
  66. // X-Socket DDR values 1LM or flat mode
  67. //
  68. #define XSOCKET_DDR_ACCESS_LATENCY 0
  69. #define XSOCKET_DDR_READ_LATENCY 1356
  70. #define XSOCKET_DDR_WRITE_LATENCY 1356
  71. #define XSOCKET_DDR_ACCESS_BANDWIDTH 0
  72. #define XSOCKET_DDR_READ_BANDWIDTH 17900
  73. #define XSOCKET_DDR_WRITE_BANDWIDTH 19100
  74. //
  75. // DDR/X-Socket DDR values 2LM when acting as cache
  76. //
  77. #define DDR2LMCACHE_ACCESS_LATENCY 0
  78. #define DDR2LMCACHE_READ_LATENCY 760
  79. #define DDR2LMCACHE_WRITE_LATENCY 760
  80. #define DDR2LMCACHE_ACCESS_BANDWIDTH 0
  81. #define DDR2LMCACHE_READ_BANDWIDTH 17900
  82. #define DDR2LMCACHE_WRITE_BANDWIDTH 12691
  83. extern struct SystemMemoryMapHob *mSystemMemoryMap;
  84. extern EFI_IIO_UDS_PROTOCOL *mIioUds;
  85. extern SOCKET_MEMORY_CONFIGURATION mSocketMemoryConfiguration;
  86. extern CPU_CSR_ACCESS_VAR *mCpuCsrAccessVarPtr;
  87. UINT8 SkippedEntries = 0;
  88. typedef enum {
  89. DDR = 0x00,
  90. DDRT,
  91. DDR2LMCACHE
  92. } MemoryType;
  93. /**
  94. Dump HMAT Header
  95. @param [in] HdrPtr Pointer to HMAT Header
  96. @retval None
  97. **/
  98. VOID
  99. DumpHeader (
  100. EFI_ACPI_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE_HEADER *HdrPtr
  101. )
  102. {
  103. DEBUG ((DEBUG_INFO, "=========== HMAT header ==========\n"));
  104. DEBUG ((DEBUG_INFO, " Signature: %.4a\n", (CHAR8 *)&HdrPtr->Header.Signature));
  105. DEBUG ((DEBUG_INFO, " Length: %d\n", HdrPtr->Header.Length));
  106. DEBUG ((DEBUG_INFO, " Revision: %Xh\n", HdrPtr->Header.Revision));
  107. DEBUG ((DEBUG_INFO, " Checksum: N/A - CHECKSUM ADDED LATER\n"));
  108. DEBUG ((DEBUG_INFO, " OemId: %.6a\n", HdrPtr->Header.OemId));
  109. DEBUG ((DEBUG_INFO, " OemTableId: %.8a\n", (CHAR8 *)&HdrPtr->Header.OemTableId));
  110. DEBUG ((DEBUG_INFO, " OemRevision: %Xh\n", HdrPtr->Header.OemRevision));
  111. DEBUG ((DEBUG_INFO, " CreatorId: %.4a\n", (CHAR8 *)&HdrPtr->Header.CreatorId));
  112. DEBUG ((DEBUG_INFO, " CreatorRevision: %Xh\n", HdrPtr->Header.CreatorRevision));
  113. DEBUG ((DEBUG_INFO, "==================================\n"));
  114. DEBUG ((DEBUG_INFO, "\n"));
  115. }
  116. /**
  117. Dump MSARS Structure
  118. @param [in] MsarsPtr Pointer to MSARS Structure
  119. @retval None
  120. **/
  121. VOID
  122. DumpMsars (
  123. MEMORY_SUBSYSTEM_ADDRESS_RANGE_STRUCTURE *MsarsPtr
  124. )
  125. {
  126. DEBUG ((DEBUG_INFO, "=========== MSARS Table =============================\n"));
  127. DEBUG ((DEBUG_INFO, " Type: %d\n", MsarsPtr->Type));
  128. DEBUG ((DEBUG_INFO, " Length: %d\n", MsarsPtr->Length));
  129. DEBUG ((DEBUG_INFO, " ProcessorDomainValid: %d\n", MsarsPtr->Flags.Bits.ProcessorDomainValid));
  130. DEBUG ((DEBUG_INFO, " MemoryDomainValid: %d\n", MsarsPtr->Flags.Bits.MemoryDomainValid));
  131. DEBUG ((DEBUG_INFO, " ReservationHint: %d\n", MsarsPtr->Flags.Bits.ReservationHint));
  132. DEBUG ((DEBUG_INFO, " ProcessorProximityDomain: %Xh\n", MsarsPtr->ProcessorProximityDomain));
  133. DEBUG ((DEBUG_INFO, " MemoryProximityDomain: %Xh\n", MsarsPtr->MemoryProximityDomain));
  134. DEBUG ((DEBUG_INFO, " SystemPhysicalAddressRangeBase: %llXh\n", MsarsPtr->AddrBase));
  135. DEBUG ((DEBUG_INFO, " SystemPhysicalAddressRangeLength: %llXh\n", MsarsPtr->AddrLength));
  136. DEBUG ((DEBUG_INFO, "=====================================================\n"));
  137. DEBUG ((DEBUG_INFO, "\n"));
  138. }
  139. /**
  140. Dump HSCIS Structure
  141. @param [in] MscisPtr Pointer to HSCIS Structure
  142. @retval None
  143. **/
  144. VOID
  145. DumpMscis (
  146. MEMORY_SIDE_CACHE_INFORMATION_STRUCTURE *MscisPtr
  147. )
  148. {
  149. UINT8 SmbiosHandleIndex;
  150. DEBUG ((DEBUG_INFO, "=========== MSCIS Table =============================\n"));
  151. DEBUG ((DEBUG_INFO, " Type: %d\n", MscisPtr->Type));
  152. DEBUG ((DEBUG_INFO, " Length: %d\n", MscisPtr->Length));
  153. DEBUG ((DEBUG_INFO, " MemoryProximityDomain: %Xh\n", MscisPtr->MemoryProximityDomain));
  154. DEBUG ((DEBUG_INFO, " MemorySideCacheSize: %llXh\n", MscisPtr->MemorySideCacheSize));
  155. DEBUG ((DEBUG_INFO, " TotalCacheLevels: %d\n", MscisPtr->CacheAttributes.Bits.TotalCacheLevels));
  156. DEBUG ((DEBUG_INFO, " CacheLevel: %d\n", MscisPtr->CacheAttributes.Bits.CacheLevel));
  157. DEBUG ((DEBUG_INFO, " CacheAssociativity: %d\n", MscisPtr->CacheAttributes.Bits.CacheAssociativity));
  158. DEBUG ((DEBUG_INFO, " WritePolicy: %d\n", MscisPtr->CacheAttributes.Bits.WritePolicy));
  159. DEBUG ((DEBUG_INFO, " CacheLineSize: %d\n", MscisPtr->CacheAttributes.Bits.CacheLineSize));
  160. DEBUG ((DEBUG_INFO, " NumSmbiosHandles: %d\n", MscisPtr->NumSmbiosHandles));
  161. for (SmbiosHandleIndex = 0; SmbiosHandleIndex < MscisPtr->NumSmbiosHandles; SmbiosHandleIndex++) {
  162. DEBUG ((DEBUG_INFO, " SmbiosHandle[%d]: %xh\n", SmbiosHandleIndex + 1 ,MscisPtr->SmbiosHandles[SmbiosHandleIndex]));
  163. }
  164. DEBUG ((DEBUG_INFO, "=====================================================\n"));
  165. DEBUG ((DEBUG_INFO, "\n"));
  166. }
  167. /**
  168. Dump LBIS Structure
  169. @param [in] LbisPtr Pointer to LBIS Structure
  170. @retval None
  171. **/
  172. VOID
  173. DumpLbis (
  174. LATENCY_BANDWIDTH_INFO_STRUCTURE *LbisPtr
  175. )
  176. {
  177. UINTN Index, Index1;
  178. UINT32 *TargetProximityDomainList;
  179. UINT16 *Entry;
  180. DEBUG ((DEBUG_INFO, "=========== MLBIS Table =============================\n"));
  181. DEBUG ((DEBUG_INFO, " Type: %d\n", LbisPtr->Type));
  182. DEBUG ((DEBUG_INFO, " Length: %d\n", LbisPtr->Length));
  183. DEBUG ((DEBUG_INFO, " Flags: %d\n", LbisPtr->Flags));
  184. DEBUG ((DEBUG_INFO, " DataType: %d\n", LbisPtr->DataType));
  185. DEBUG ((DEBUG_INFO, " InitiatorProximityDomainsNumber: %d\n", LbisPtr->InitiatorProximityDomainsNumber));
  186. DEBUG ((DEBUG_INFO, " TargetProximityDomainsNumber: %d\n", LbisPtr->TargetProximityDomainsNumber));
  187. DEBUG ((DEBUG_INFO, " EntryBaseUnit: %lXh\n", LbisPtr->EntryBaseUnit));
  188. DEBUG ((DEBUG_INFO, " InitiatorProximityDomainList:\n"));
  189. for (Index = 0; Index < LbisPtr->InitiatorProximityDomainsNumber; Index++) {
  190. DEBUG ((DEBUG_INFO, " %d ", LbisPtr->InitiatorProximityDomainList[Index]));
  191. }
  192. TargetProximityDomainList = (UINT32*)&(LbisPtr->InitiatorProximityDomainList[Index]);
  193. DEBUG ((DEBUG_INFO, "\n"));
  194. DEBUG ((DEBUG_INFO, " TargetProximityDomainList:\n"));
  195. for (Index = 0; Index < LbisPtr->TargetProximityDomainsNumber; Index++) {
  196. DEBUG ((DEBUG_INFO, " %d ", TargetProximityDomainList[Index]));
  197. }
  198. Entry = (UINT16*)(TargetProximityDomainList + Index);
  199. DEBUG ((DEBUG_INFO, "\n"));
  200. DEBUG ((DEBUG_INFO, "RelativeDistanceEntry:\n"));
  201. for (Index = 0; Index < LbisPtr->InitiatorProximityDomainsNumber; Index++) {
  202. for (Index1 = 0; Index1 < LbisPtr->TargetProximityDomainsNumber; Index1++) {
  203. DEBUG ((DEBUG_INFO, " %d ", *(Entry + (Index * LbisPtr->TargetProximityDomainsNumber) + Index1)));
  204. }
  205. DEBUG ((DEBUG_INFO, "\n"));
  206. }
  207. DEBUG ((DEBUG_INFO, "\n"));
  208. DEBUG ((DEBUG_INFO, "=====================================================\n"));
  209. DEBUG ((DEBUG_INFO, "\n"));
  210. }
  211. /**
  212. Dump HMAT table
  213. @param [in] HmatAcpiTable Pointer to HMAT table.
  214. @retval None
  215. **/
  216. VOID
  217. DumpHmat (
  218. EFI_ACPI_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE *HmatAcpiTable
  219. )
  220. {
  221. UINT32 TotalLength = HmatAcpiTable->HmatHeader.Header.Length;
  222. UINT8 *Table = (UINT8 *)HmatAcpiTable;
  223. UINT32 Length;
  224. UINT16 Type;
  225. DumpHeader (&HmatAcpiTable->HmatHeader);
  226. Length = sizeof (EFI_ACPI_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE_HEADER);
  227. Table += Length;
  228. TotalLength -= Length;
  229. //
  230. // Dump tables
  231. //
  232. while (TotalLength) {
  233. Type = ((MEMORY_SUBSYSTEM_ADDRESS_RANGE_STRUCTURE *)Table)->Type;
  234. //
  235. // For HBM will need to add LBIS structure
  236. //
  237. if (Type == MEMORY_SUBSYSTEM_ADDRESS_RANGE_STRUCTURE_TYPE) {
  238. DumpMsars ((MEMORY_SUBSYSTEM_ADDRESS_RANGE_STRUCTURE *)Table);
  239. } else if (Type == MEMORY_SIDE_CACHE_INFORMATION_STRUCTURE_TYPE) {
  240. DumpMscis ((MEMORY_SIDE_CACHE_INFORMATION_STRUCTURE *)Table);
  241. } else {
  242. DumpLbis ((LATENCY_BANDWIDTH_INFO_STRUCTURE *)Table);
  243. }
  244. //
  245. // Goto next entry
  246. //
  247. Length = ((MEMORY_SUBSYSTEM_ADDRESS_RANGE_STRUCTURE *)Table)->Length;
  248. Table += Length;
  249. TotalLength -= Length;
  250. }
  251. }
  252. /**
  253. Update SMBIOS handles and number of SMBIOS handles which is related to specified NodeId to MEMORY_DOMAIN_LIST_INFO
  254. SMBIOS Type 17 handles are formed in sequence order. First handle is S0 C0 D0, Second handle is S0 C0 D1 and so on.
  255. So we loop in this order to find the handles of DDR which is part of the specific 2LM cache memory.
  256. @param [in] HmatData Points to HMAT structure
  257. @param [in] NodeId SMBIOS handles related to this NodeId will be retrieved
  258. @retval None
  259. **/
  260. VOID
  261. UpdateSmbiosHandles(
  262. IN HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData,
  263. IN UINT32 NodeId,
  264. IN UINT8 Socket,
  265. IN UINT32 ImcBitMap
  266. )
  267. {
  268. EFI_STATUS Status;
  269. STATIC EFI_SMBIOS_PROTOCOL *Smbios = NULL;
  270. SMBIOS_TABLE_TYPE17 *Type17Record;
  271. EFI_SMBIOS_TABLE_HEADER *SmbiosRecord;
  272. EFI_SMBIOS_HANDLE SmbiosHandle;
  273. EFI_SMBIOS_TYPE SmbiosType;
  274. UINT8 Loop = 1;
  275. UINT8 SlotsPerImc = MAX_DIMM * MAX_MC_CH;
  276. UINT8 DimmsPerImc = 0;
  277. Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **) &Smbios);
  278. if (EFI_ERROR (Status)) {
  279. return ;
  280. }
  281. SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
  282. SmbiosType = 17;
  283. //
  284. // Adjust ImcBitMap according to the socket number
  285. //
  286. if (Socket != 0) {
  287. ImcBitMap <<= (Socket * SlotsPerImc);
  288. }
  289. if (!PcdGetBool (PcdHalfWidth)) {
  290. DimmsPerImc = SlotsPerImc;
  291. } else {
  292. DimmsPerImc = SlotsPerImc - 1;
  293. }
  294. do {
  295. Status = Smbios->GetNext(Smbios, &SmbiosHandle, &SmbiosType, &SmbiosRecord, NULL);
  296. if (!EFI_ERROR (Status) && (SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED)) {
  297. Type17Record = (SMBIOS_TABLE_TYPE17 *)SmbiosRecord;
  298. //
  299. // 1) check whether the Memory device of this record is cache capable(ie, 2LM DDR cache) and
  300. // 2) this memory handle is to the current looping IMC
  301. //
  302. if ((Type17Record->TypeDetail.CacheDram) && (ImcBitMap & BIT0)) {
  303. HmatData->MemoryDomainList[NodeId].SmbiosHandles[HmatData->MemoryDomainList[NodeId].NumSmbiosHandles] = Type17Record->Hdr.Handle ;
  304. HmatData->MemoryDomainList[NodeId].NumSmbiosHandles++;
  305. }
  306. }
  307. //
  308. // if loop done for this IMC then move for next
  309. //
  310. if (Loop % DimmsPerImc == 0) {
  311. ImcBitMap >>= 1;
  312. }
  313. ++Loop;
  314. } while (!EFI_ERROR (Status) && (SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED) && (ImcBitMap != 0));
  315. }
  316. /**
  317. Remove slack by moving this substructure lower which removes unused memory.
  318. @param [in] SlackSize Points to cumulative unused memory size
  319. @param [in] Src Points to memory to move
  320. @param [in] SrcLen Size of memory to move
  321. @retval None
  322. **/
  323. VOID
  324. RemoveSlack (
  325. IN UINTN *SlackSize,
  326. IN VOID *Src,
  327. IN UINTN SrcLen
  328. )
  329. {
  330. VOID *Dst;
  331. Dst = (UINT8 *)Src - (*SlackSize);
  332. CopyMem (Dst, Src, SrcLen);
  333. }
  334. /**
  335. Calculate the Memory Proximity Domain Number and generate its associate list.
  336. @param [in, out] HmatData Pointer to HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE to be filled
  337. @retval None.
  338. **/
  339. VOID
  340. GetMemoryDomains (
  341. IN OUT HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData
  342. )
  343. {
  344. UINT64 MemorySideCacheSize;
  345. UINT32 NodeId;
  346. UINT32 LastDomainId = 0;
  347. UINT8 Index;
  348. UINT8 PrevIndex;
  349. UINT8 LastIndex = 0;
  350. UINT8 Mc;
  351. UINT8 Socket;
  352. UINT8 McBitmap[EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS];
  353. UINT32 PmemEntry[EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS];
  354. UINT64 MemoryAddressStore[EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS];
  355. UINT64 MemoryAddress;
  356. UINT8 MaxEnabledImc = 0;
  357. UINTN ImcIndex;
  358. UINT8 MemSocketBitmap = 0;
  359. UINT8 NoMemSocketBitmap;
  360. BOOLEAN SkipEntry;
  361. BOOLEAN UpdateSmbiosHandle = FALSE;
  362. EFI_STATUS Status = EFI_SUCCESS;
  363. DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
  364. Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, (VOID **) &DynamicSiLibraryProtocol2);
  365. if (EFI_ERROR (Status)) {
  366. ASSERT_EFI_ERROR (Status);
  367. return;
  368. }
  369. HmatData->MemoryDomainNumber = 0;
  370. ZeroMem (McBitmap, sizeof(McBitmap));
  371. ZeroMem (MemoryAddressStore, sizeof(MemoryAddressStore));
  372. //
  373. // Memory Proximity Domain must match the Domain in the SRAT Memory Affinity structure
  374. //
  375. for (Index = 0; Index < mSystemMemoryMap->numberEntries; Index++) {
  376. //
  377. // Skip any memory region marked reserved
  378. //
  379. if (DynamicSiLibraryProtocol2->IsMemTypeReserved (mSystemMemoryMap->Element[Index].Type)) {
  380. continue;
  381. }
  382. if (!DynamicSiLibraryProtocol2->IsMemTypeVolatile (mSystemMemoryMap->Element[Index].Type)) {
  383. //
  384. // Skip all non volatile regions
  385. //
  386. PmemEntry[SkippedEntries] = Index;
  387. SkippedEntries++;
  388. continue;
  389. }
  390. SkipEntry = FALSE;
  391. MemoryAddress = LShiftU64 (mSystemMemoryMap->Element[Index].BaseAddress, MEM_ADDR_SHFT_VAL);
  392. //
  393. // Skip duplicate entries
  394. //
  395. if (Index) {
  396. for (PrevIndex = 0; PrevIndex < Index; PrevIndex++) {
  397. if (MemoryAddress == MemoryAddressStore[PrevIndex]) {
  398. SkipEntry = TRUE;
  399. break;
  400. }
  401. }
  402. }
  403. if (SkipEntry) {
  404. continue;
  405. }
  406. MemoryAddressStore[Index] = MemoryAddress;
  407. LastIndex = Index;
  408. for (ImcIndex = 0, MaxEnabledImc = 0; ImcIndex < MAX_IMC; ImcIndex++) {
  409. if (mSystemMemoryMap->Socket[mSystemMemoryMap->Element[Index].SocketId].imcEnabled[ImcIndex] != 0) {
  410. MaxEnabledImc ++;
  411. }
  412. }
  413. //
  414. // Update bitmap for sockets with memory populated
  415. //
  416. MemSocketBitmap |= BIT0 << mSystemMemoryMap->Element[Index].SocketId;
  417. //
  418. // Get memory domain (must match SRAT memory domain)
  419. //
  420. NodeId = ProximityDomainOf (
  421. mSystemMemoryMap->Element[Index].SocketId,
  422. mSystemMemoryMap->Element[Index].Type,
  423. MaxEnabledImc,
  424. HmatData->SncEnabled,
  425. HmatData->SncNumOfCluster,
  426. mSystemMemoryMap->Element[Index].ImcInterBitmap,
  427. mSystemMemoryMap->volMemMode,
  428. LastDomainId
  429. );
  430. NodeId = (NodeId * HmatData->VirtualNumOfCluster) + (Index % HmatData->VirtualNumOfCluster);
  431. if (LastDomainId < NodeId) {
  432. LastDomainId = NodeId;
  433. }
  434. if (NodeId >= EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS) {
  435. DEBUG ((DEBUG_ERROR, "[ACPI] (HMAT) ERROR: Invalid Memory Proximity Domain (0x%x)\n", NodeId));
  436. ASSERT (FALSE);
  437. }
  438. //
  439. // Update map of indexes included in this memory domain
  440. //
  441. HmatData->MemoryDomainList[NodeId].MemMapIndexMap |= LShiftU64 (BIT0, Index);
  442. //
  443. // Update Memory domain count and set domain to valid
  444. // Prevent counting repeated entries with the same Proximity Domain ID
  445. //
  446. if ((Index == 0) || (HmatData->MemoryDomainList[NodeId].Valid == 0)) {
  447. HmatData->MemoryDomainNumber++;
  448. HmatData->MemoryDomainList[NodeId].PhysicalSocketId = mSystemMemoryMap->Element[Index].SocketId;
  449. HmatData->MemoryDomainList[NodeId].Valid = 1;
  450. McBitmap[NodeId] = 0;
  451. }
  452. if (HmatData->MemoryDomainList[NodeId].Valid) {
  453. if (mSystemMemoryMap->Element[Index].Type == MemType2lmDdrCacheMemoryMode) {
  454. //
  455. // Set up side cache info for 2LM
  456. //
  457. HmatData->MemoryDomainList[NodeId].Cacheable = 1;
  458. //
  459. // Calculate MemorySideCacheSize
  460. // MemorySideCacheSize for each MC is the DDR4 memSize
  461. //
  462. MemorySideCacheSize = 0;
  463. UpdateSmbiosHandle = FALSE;
  464. for (Mc = 0; Mc < MAX_IMC; Mc++) {
  465. if ((mSystemMemoryMap->Element[Index].ImcInterBitmap & (BIT0 << Mc)) && !(McBitmap[NodeId] & (BIT0 << Mc))) {
  466. UpdateSmbiosHandle = TRUE;
  467. if (mSystemMemoryMap->volMemMode == VOL_MEM_MODE_2LM) {
  468. MemorySideCacheSize += mSystemMemoryMap->Socket[mSystemMemoryMap->Element[Index].SocketId].imc[Mc].MemSize;
  469. } else{ // VOL_MEM_MODE_MIX_1LM2LM
  470. MemorySideCacheSize += mSystemMemoryMap->DdrCacheSize[mSystemMemoryMap->Element[Index].SocketId][Mc];
  471. }
  472. }
  473. }
  474. if (UpdateSmbiosHandle) {
  475. UpdateSmbiosHandles (
  476. HmatData,
  477. NodeId,
  478. mSystemMemoryMap->Element[Index].SocketId,
  479. mSystemMemoryMap->Element[Index].ImcInterBitmap
  480. );
  481. }
  482. HmatData->MemoryDomainList[NodeId].MemorySideCacheSize += MemorySideCacheSize;
  483. }
  484. McBitmap[NodeId] |= mSystemMemoryMap->Element[Index].ImcInterBitmap;
  485. }
  486. DEBUG ((DEBUG_INFO, "MemoryDomainList[%x] Valid = %x Cacheable = %x MemorySideCacheSize = %x\n",
  487. NodeId,
  488. HmatData->MemoryDomainList[NodeId].Valid,
  489. HmatData->MemoryDomainList[NodeId].Cacheable,
  490. HmatData->MemoryDomainList[NodeId].MemorySideCacheSize
  491. ));
  492. }
  493. //
  494. // Update LastDomainId for enabled sockets with no memory
  495. //
  496. NoMemSocketBitmap = mCpuCsrAccessVarPtr->socketPresentBitMap & ~MemSocketBitmap;
  497. for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
  498. if ((BIT0 << Socket) & NoMemSocketBitmap) {
  499. LastDomainId += HmatData->SncNumOfCluster;
  500. }
  501. }
  502. //
  503. // Add skipped entries
  504. //
  505. for (Index = 0; Index < SkippedEntries; Index++) {
  506. SkipEntry = FALSE;
  507. MemoryAddress = LShiftU64 (mSystemMemoryMap->Element[PmemEntry[Index]].BaseAddress, MEM_ADDR_SHFT_VAL);
  508. //
  509. // Skip duplicate entries
  510. //
  511. for (PrevIndex = 0; PrevIndex < LastIndex; PrevIndex++) {
  512. if (MemoryAddress == MemoryAddressStore[PrevIndex]) {
  513. SkipEntry = TRUE;
  514. break;
  515. }
  516. }
  517. if (SkipEntry) {
  518. continue;
  519. }
  520. MemoryAddressStore[LastIndex++] = MemoryAddress;
  521. //
  522. // Get memory domain (must match SRAT memory domain)
  523. //
  524. NodeId = ProximityDomainOf (
  525. mSystemMemoryMap->Element[PmemEntry[Index]].SocketId,
  526. mSystemMemoryMap->Element[PmemEntry[Index]].Type,
  527. MaxEnabledImc,
  528. HmatData->SncEnabled,
  529. HmatData->SncNumOfCluster,
  530. mSystemMemoryMap->Element[PmemEntry[Index]].ImcInterBitmap,
  531. mSystemMemoryMap->volMemMode,
  532. LastDomainId
  533. );
  534. NodeId = (NodeId * HmatData->VirtualNumOfCluster) + (Index % HmatData->VirtualNumOfCluster);
  535. if (LastDomainId < NodeId) {
  536. LastDomainId = NodeId;
  537. }
  538. if (NodeId >= EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS) {
  539. DEBUG ((DEBUG_ERROR, "[ACPI] (HMAT) ERROR: Invalid Memory Proximity Domain (0x%x)\n", NodeId));
  540. ASSERT (FALSE);
  541. }
  542. //
  543. // Update map of indexes included in this memory domain
  544. //
  545. HmatData->MemoryDomainList[NodeId].MemMapIndexMap |= LShiftU64 (BIT0, PmemEntry[Index]);
  546. //
  547. // Update Memory domain count and set domain to valid
  548. // Prevent counting repeated entries with the same Proximity Domain ID
  549. //
  550. if ((PmemEntry[Index] == 0) || (HmatData->MemoryDomainList[NodeId].Valid == 0)) {
  551. HmatData->MemoryDomainNumber++;
  552. HmatData->MemoryDomainList[NodeId].PhysicalSocketId = mSystemMemoryMap->Element[PmemEntry[Index]].SocketId;
  553. HmatData->MemoryDomainList[NodeId].Valid = 1;
  554. }
  555. DEBUG ((DEBUG_INFO, "[ACPI] (HMAT) MemoryDomainList[%x] Valid = %x Cacheable = %x MemorySideCacheSize = %x\n",
  556. NodeId,
  557. HmatData->MemoryDomainList[NodeId].Valid,
  558. HmatData->MemoryDomainList[NodeId].Cacheable,
  559. HmatData->MemoryDomainList[NodeId].MemorySideCacheSize
  560. ));
  561. }
  562. }
  563. /**
  564. Calculate the Processor Proximity Domain Number and generate its associate list.
  565. @param [in, out] HmatData Pointer to HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE to be filled
  566. @retval None.
  567. **/
  568. VOID
  569. GetProcessorDomains (
  570. IN OUT HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData
  571. )
  572. {
  573. UINT32 NodeId;
  574. UINT8 Index;
  575. INTN FirstImc;
  576. UINT8 SocketId;
  577. UINT8 SocketLogicalId;
  578. UINT8 MemSocketBitmap;
  579. UINT8 NoMemSocketBitmap;
  580. EFI_STATUS Status = EFI_SUCCESS;
  581. DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
  582. Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, (VOID **) &DynamicSiLibraryProtocol2);
  583. if (EFI_ERROR (Status)) {
  584. ASSERT_EFI_ERROR (Status);
  585. return;
  586. }
  587. MemSocketBitmap = 0;
  588. NoMemSocketBitmap = 0;
  589. HmatData->ProcessorDomainNumber = 0;
  590. //
  591. // Processor Proximity Domain must match the Domain in the SRAT APIC or X2APIC Affinity Structure
  592. //
  593. for (Index = 0; Index < mSystemMemoryMap->numberEntries; Index++) {
  594. //
  595. // Skip any memory region marked reserved or FPGA
  596. //
  597. if (DynamicSiLibraryProtocol2->IsMemTypeReserved (mSystemMemoryMap->Element[Index].Type) || DynamicSiLibraryProtocol2->IsMemTypeFpga (mSystemMemoryMap->Element[Index].Type)) {
  598. continue;
  599. }
  600. SocketId = mSystemMemoryMap->Element[Index].SocketId;
  601. SocketLogicalId = GetSocketLogicalId (SocketId);
  602. //
  603. // Get processor proximity domain
  604. //
  605. if (HmatData->SncEnabled || HmatData->VirtualNumaEnabled) {
  606. FirstImc = LowBitSet32 (mSystemMemoryMap->Element[Index].ImcInterBitmap);
  607. if (FirstImc == -1) {
  608. FirstImc = 0;
  609. }
  610. //
  611. // Find the 1st IMC according the interbitmap
  612. //
  613. if (MAX_IMC <= HmatData->SncNumOfCluster) {
  614. NodeId = (SocketLogicalId * HmatData->SncNumOfCluster) + (UINT32)FirstImc;
  615. } else {
  616. NodeId = (SocketLogicalId * HmatData->SncNumOfCluster) + ((UINT32)FirstImc) / HmatData->SncNumOfCluster;
  617. }
  618. NodeId = (NodeId * HmatData->VirtualNumOfCluster) + (Index % HmatData->VirtualNumOfCluster);
  619. DEBUG ((DEBUG_INFO, "%a: SocketId: 0x%x SncNumOfCluster: 0x%x ImcInterBitmap:0x%x and NodeId:0x%x\n",
  620. __FUNCTION__, mSystemMemoryMap->Element[Index].SocketId, HmatData->SncNumOfCluster, mSystemMemoryMap->Element[Index].ImcInterBitmap, NodeId));
  621. } else {
  622. NodeId = SocketLogicalId;
  623. }
  624. if (NodeId >= EFI_ACPI_HMAT_NUMBER_OF_PROCESSOR_DOMAINS) {
  625. DEBUG ((DEBUG_ERROR, "[ACPI] (HMAT) ERROR: Invalid Processor Proximity Domain (0x%x)\n", NodeId));
  626. return;
  627. }
  628. //
  629. // Update processor domain count and set domain to valid
  630. // Prevent counting repeated entries with the same Proximity Domain ID
  631. //
  632. if ((Index == 0) || (HmatData->ProcessorDomainList[NodeId] == 0)) {
  633. HmatData->ProcessorDomainNumber++;
  634. HmatData->ProcessorDomainSocketIdList[NodeId] = SocketId;
  635. HmatData->ProcessorDomainList[NodeId] = 1; // Domain is valid
  636. MemSocketBitmap |= (BIT0 << mSystemMemoryMap->Element[Index].SocketId);
  637. }
  638. DEBUG ((DEBUG_INFO, "[ACPI] (HMAT) ProcessorDomainList[%x] Valid = %x\n", NodeId, HmatData->ProcessorDomainList[NodeId]));
  639. }
  640. //
  641. // Update processor domain for enabled sockets without memory
  642. //
  643. NoMemSocketBitmap = mCpuCsrAccessVarPtr->socketPresentBitMap & ~MemSocketBitmap;
  644. for (SocketId = 0; SocketId < MAX_SOCKET; SocketId++) {
  645. if ((BIT0 << SocketId) & NoMemSocketBitmap) {
  646. for (Index = 0; Index < (HmatData->SncNumOfCluster * HmatData->VirtualNumOfCluster); Index++) {
  647. NodeId = GetSocketLogicalId (SocketId) * HmatData->SncNumOfCluster * HmatData->VirtualNumOfCluster + Index;
  648. HmatData->ProcessorDomainNumber++;
  649. HmatData->ProcessorDomainSocketIdList[NodeId] = SocketId;
  650. HmatData->ProcessorDomainList[NodeId] = 1;
  651. }
  652. }
  653. }
  654. }
  655. /**
  656. Initialize HMAT Data to be consumed when populating tables.
  657. This Functions allocates buffer for HMAT Data, so it is caller responsibility to free it.
  658. @param None.
  659. @retval Pointer to allocated HMAT Data if it was initialized correctly.
  660. @retval NULL if not allocated and not initialized correctly.
  661. **/
  662. UINTN *
  663. InitializeHmatData (
  664. VOID
  665. )
  666. {
  667. HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData = NULL;
  668. HmatData = AllocateZeroPool (sizeof (HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE));
  669. if (HmatData == NULL) {
  670. DEBUG ((DEBUG_ERROR, "[ACPI] (HMAT) ERROR: Could not allocate HmatData structure pointer\n"));
  671. return (UINTN *) HmatData;
  672. }
  673. if (mIioUds->IioUdsPtr->SystemStatus.OutSncEn) {
  674. HmatData->SncEnabled = 1;
  675. HmatData->SncNumOfCluster = mIioUds->IioUdsPtr->SystemStatus.OutNumOfCluster;
  676. } else {
  677. HmatData->SncNumOfCluster = 1;
  678. }
  679. if (mSystemMemoryMap->VirtualNumaEnable) {
  680. HmatData->VirtualNumaEnabled = 1;
  681. HmatData->VirtualNumOfCluster = mSystemMemoryMap->VirtualNumOfCluster;
  682. } else {
  683. HmatData->VirtualNumOfCluster = 1;
  684. }
  685. GetProcessorDomains (HmatData);
  686. GetMemoryDomains (HmatData);
  687. return (UINTN *)HmatData;
  688. }
  689. /**
  690. Patch HMAT MSARS substructure.
  691. @param [in, out] HmatAcpiTable Points to HMAT table to be modified
  692. @param [in, out] SlackSize Points to cumulative slack size
  693. @param [in] HmatData HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE to be consumed
  694. @retval None
  695. **/
  696. VOID
  697. PatchHmatMsars (
  698. IN OUT EFI_ACPI_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE *HmatAcpiTable,
  699. IN OUT UINTN *SlackSize,
  700. IN HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData
  701. )
  702. {
  703. UINT32 Index;
  704. UINT32 PrevIndex;
  705. UINT32 MemoryNodeId;
  706. UINT32 ProcessorNodeId;
  707. UINT32 Count = 0;
  708. UINT32 UnusedCount;
  709. UINT8 MemoryNodeValid;
  710. UINT16 ProcessorNodeValid;
  711. UINT64 MemoryAddress;
  712. BOOLEAN SkipEntry;
  713. INTN FirstImc;
  714. UINT8 SocketLogicalId;
  715. EFI_STATUS Status = EFI_SUCCESS;
  716. DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
  717. Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, (VOID **) &DynamicSiLibraryProtocol2);
  718. if (EFI_ERROR (Status)) {
  719. ASSERT_EFI_ERROR (Status);
  720. return;
  721. }
  722. DEBUG ((DEBUG_INFO, "[ACPI] (HMAT) Populating Memory Subsystem Address Range Structure\n"));
  723. for (Index = 0; Index < mSystemMemoryMap->numberEntries; Index++) {
  724. //
  725. // Skip any memory region marked reserved
  726. //
  727. DEBUG ((DEBUG_INFO, "[ACPI] mSystemMemoryMap->Element[%d].Type = 0x%x\n",Index, mSystemMemoryMap->Element[Index].Type));
  728. if (DynamicSiLibraryProtocol2->IsMemTypeReserved (mSystemMemoryMap->Element[Index].Type)) {
  729. continue;
  730. }
  731. if (Count >= EFI_ACPI_HMAT_MSARS_COUNT) {
  732. DEBUG ((DEBUG_INFO, "[ACPI] (HMAT) Invalid MSARS entry with Index = 0x%x\n", Count));
  733. ASSERT (FALSE);
  734. break;
  735. }
  736. SkipEntry = FALSE;
  737. //
  738. // Skip duplicate entries
  739. //
  740. MemoryAddress = LShiftU64 (mSystemMemoryMap->Element[Index].BaseAddress, MEM_ADDR_SHFT_VAL);
  741. if (Count) {
  742. for (PrevIndex = 0; PrevIndex < Count; PrevIndex++) {
  743. if (MemoryAddress == HmatAcpiTable->Msars[PrevIndex].AddrBase) {
  744. SkipEntry = TRUE;
  745. break;
  746. }
  747. }
  748. }
  749. if (SkipEntry) {
  750. continue;
  751. }
  752. //
  753. // Find memory domain for this index
  754. //
  755. for (MemoryNodeId = 0; MemoryNodeId < EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS; MemoryNodeId++) {
  756. if (HmatData->MemoryDomainList[MemoryNodeId].MemMapIndexMap & LShiftU64(BIT0, Index)) {
  757. break;
  758. }
  759. }
  760. //
  761. // Fill in valid field
  762. //
  763. if (MemoryNodeId < EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS) {
  764. MemoryNodeValid = HmatData->MemoryDomainList[MemoryNodeId].Valid;
  765. } else {
  766. MemoryNodeValid = 0;
  767. }
  768. //
  769. // Get processor domain for this index
  770. //
  771. if (DynamicSiLibraryProtocol2->IsMemTypeFpga (mSystemMemoryMap->Element[Index].Type)) {
  772. ProcessorNodeValid = 0; // There is no processor for FPGA.
  773. ProcessorNodeId = 0; // This field will be ingored for FPGA.
  774. } else {
  775. SocketLogicalId = GetSocketLogicalId (mSystemMemoryMap->Element[Index].SocketId);
  776. if (HmatData->SncEnabled || HmatData->VirtualNumaEnabled) {
  777. FirstImc = LowBitSet32 (mSystemMemoryMap->Element[Index].ImcInterBitmap);
  778. if (FirstImc == -1) {
  779. FirstImc = 0;
  780. }
  781. //
  782. // Find the 1st IMC according the interbitmap
  783. //
  784. if (MAX_IMC <= HmatData->SncNumOfCluster) {
  785. ProcessorNodeId = (SocketLogicalId * HmatData->SncNumOfCluster) + (UINT32)FirstImc;
  786. } else {
  787. ProcessorNodeId = (SocketLogicalId * HmatData->SncNumOfCluster) + ((UINT32)FirstImc) / HmatData->SncNumOfCluster;
  788. }
  789. ProcessorNodeId = (ProcessorNodeId * HmatData->VirtualNumOfCluster) + (Index % HmatData->VirtualNumOfCluster);
  790. DEBUG ((DEBUG_INFO, "%a: SocketId: 0x%x SncNumOfCluster: 0x%x ImcInterBitmap:0x%x and NodeId:0x%x \n",
  791. __FUNCTION__, mSystemMemoryMap->Element[Index].SocketId, HmatData->SncNumOfCluster, mSystemMemoryMap->Element[Index].ImcInterBitmap, ProcessorNodeId));
  792. } else {
  793. ProcessorNodeId = SocketLogicalId;
  794. }
  795. //
  796. // Fill in valid field
  797. //
  798. if (ProcessorNodeId < EFI_ACPI_HMAT_NUMBER_OF_PROCESSOR_DOMAINS) {
  799. ProcessorNodeValid = HmatData->ProcessorDomainList[ProcessorNodeId];
  800. } else {
  801. ProcessorNodeValid = 0;
  802. }
  803. }
  804. //
  805. // The HOB has base addr in 64 MB chunks
  806. //
  807. HmatAcpiTable->Msars[Count].AddrBase = MemoryAddress;
  808. HmatAcpiTable->Msars[Count].AddrLength = LShiftU64 (mSystemMemoryMap->Element[Index].ElementSize, MEM_ADDR_SHFT_VAL);
  809. HmatAcpiTable->Msars[Count].Flags.Value = 0;
  810. //
  811. // Fill in Proximity Domains
  812. //
  813. HmatAcpiTable->Msars[Count].ProcessorProximityDomain = ProcessorNodeId;
  814. HmatAcpiTable->Msars[Count].Flags.Bits.ProcessorDomainValid = ProcessorNodeValid;
  815. HmatAcpiTable->Msars[Count].MemoryProximityDomain = MemoryNodeId;
  816. HmatAcpiTable->Msars[Count].Flags.Bits.MemoryDomainValid = MemoryNodeValid;
  817. DEBUG ((DEBUG_INFO, "[ACPI] (HMAT) MSARS[%x] AddrBase = 0x%lx, AddrLength = 0x%lx, MemDomain = %x, ProcDomain = %x\n",
  818. Count,
  819. HmatAcpiTable->Msars[Count].AddrBase,
  820. HmatAcpiTable->Msars[Count].AddrLength,
  821. MemoryNodeId,
  822. ProcessorNodeId
  823. ));
  824. Count++;
  825. }
  826. //
  827. // Update SlackSize for unused MSARS entries
  828. //
  829. UnusedCount = EFI_ACPI_HMAT_MSARS_COUNT - Count;
  830. *SlackSize += UnusedCount * sizeof(HmatAcpiTable->Msars[0]);
  831. }
  832. /**
  833. Prints HMAT LATENCY_BANDWIDTH_INFO_STRUCTURE for debug purposes.
  834. @param [in] Lbis Points to HMAT LATENCY_BANDWIDTH_INFO_STRUCTURE to be printed.
  835. @retval None.
  836. **/
  837. VOID
  838. PrintLbisHmat (
  839. IN LATENCY_BANDWIDTH_INFO_STRUCTURE *Lbis
  840. )
  841. {
  842. UINT32 Row = 0;
  843. UINT32 Col = 0;
  844. UINT32 RowBaseIndex = 0;
  845. UINT16 *Entry;
  846. Entry = (UINT16 *) Lbis->RelativeDistanceEntry;
  847. DEBUG ((DEBUG_INFO, "[ACPI] (HMAT) SLLBIS Data: "));
  848. DEBUG ((DEBUG_INFO, "InitiatorNumber = %d, TargetNumber = %d. ", Lbis->InitiatorProximityDomainsNumber, Lbis->TargetProximityDomainsNumber));
  849. DEBUG ((DEBUG_INFO, "Entry Base Unit = %d \n", Lbis->EntryBaseUnit));
  850. DEBUG ((DEBUG_INFO, " "));
  851. for (Col = 0; Col < Lbis->TargetProximityDomainsNumber; Col++) {
  852. DEBUG ((DEBUG_INFO, "%02d ", Lbis->TargetProximityDomainList[Col]));
  853. }
  854. DEBUG ((DEBUG_INFO, "\n"));
  855. for (Row = 0; Row < Lbis->InitiatorProximityDomainsNumber; Row++) {
  856. RowBaseIndex = Row * Lbis->TargetProximityDomainsNumber;
  857. DEBUG ((DEBUG_INFO, "%02d ", Lbis->InitiatorProximityDomainList[Row]));
  858. for (Col = 0; Col < Lbis->TargetProximityDomainsNumber; Col++) {
  859. DEBUG ((DEBUG_INFO, "%08d ", Entry[RowBaseIndex + Col]));
  860. }
  861. DEBUG ((DEBUG_INFO, "\n"));
  862. }
  863. }
  864. /**
  865. Get the Read/Write/Access bandwidth value of the memory type.
  866. @param [in] DataType Type of bandwidth value that is required. (Read/Write/Access)
  867. @param [in] Type Type of memory for which Bandwidth is required. (DDR/DDRT)
  868. @retval Value of the bandwidth associated with memory type.
  869. @retval 0xFF Input parameters are invalid.
  870. **/
  871. UINT16
  872. GetMemoryBandWidth (
  873. IN UINT8 DataType,
  874. IN MemoryType Type,
  875. IN UINT8 volMemMode
  876. )
  877. {
  878. if (Type == DDRT) { // MemoryType == DDRT
  879. switch (DataType) {
  880. case EFI_ACPI_HMAT_ACCESS_BANDWIDTH :
  881. return DDRT_ACCESS_BANDWIDTH;
  882. case EFI_ACPI_HMAT_READ_BANDWIDTH :
  883. if (volMemMode == VOL_MEM_MODE_1LM) {
  884. return DDRT_1LM_READ_BANDWIDTH;
  885. } else {
  886. return DDRT_2LM_READ_BANDWIDTH;
  887. }
  888. case EFI_ACPI_HMAT_WRITE_BANDWIDTH :
  889. if (volMemMode == VOL_MEM_MODE_1LM) {
  890. return DDRT_1LM_WRITE_BANDWIDTH;
  891. } else {
  892. return DDRT_2LM_WRITE_BANDWIDTH;
  893. }
  894. default:
  895. return 0xFF;
  896. }
  897. } else if (Type == DDR2LMCACHE) {
  898. switch (DataType) {
  899. case EFI_ACPI_HMAT_ACCESS_BANDWIDTH :
  900. return DDR2LMCACHE_ACCESS_BANDWIDTH;
  901. case EFI_ACPI_HMAT_READ_BANDWIDTH :
  902. return DDR2LMCACHE_READ_BANDWIDTH;
  903. case EFI_ACPI_HMAT_WRITE_BANDWIDTH :
  904. return DDR2LMCACHE_WRITE_BANDWIDTH;
  905. default:
  906. return 0xFF;
  907. }
  908. } else {
  909. switch (DataType) {
  910. case EFI_ACPI_HMAT_ACCESS_BANDWIDTH :
  911. return DDR_ACCESS_BANDWIDTH;
  912. case EFI_ACPI_HMAT_READ_BANDWIDTH :
  913. return DDR_READ_BANDWIDTH;
  914. case EFI_ACPI_HMAT_WRITE_BANDWIDTH :
  915. return DDR_WRITE_BANDWIDTH;
  916. default:
  917. return 0xFF;
  918. }
  919. }
  920. }
  921. /**
  922. Get the Read/Write/Access bandwidth value of the memory type across sockets.
  923. @param [in] DataType Type of bandwidth value that is required. (Read/Write/Access)
  924. @param [in] Type Type of memory for which Bandwidth is required. (DDR/DDRT)
  925. @retval Value of the bandwidth associated with memory type.
  926. @retval 0xFF Input parameters are invalid.
  927. **/
  928. UINT16
  929. GetXSocketMemoryBandWidth (
  930. IN UINT8 DataType,
  931. IN MemoryType Type,
  932. IN UINT8 volMemMode
  933. )
  934. {
  935. if (Type == DDRT) { // MemoryType == DDRT
  936. switch (DataType) {
  937. case EFI_ACPI_HMAT_ACCESS_BANDWIDTH:
  938. return DDRT_ACCESS_BANDWIDTH;
  939. case EFI_ACPI_HMAT_READ_BANDWIDTH:
  940. if (volMemMode == VOL_MEM_MODE_1LM) {
  941. return XSOCKET_DDRT_1LM_READ_BANDWIDTH;
  942. } else {
  943. return XSOCKET_DDRT_2LM_READ_BANDWIDTH;
  944. }
  945. case EFI_ACPI_HMAT_WRITE_BANDWIDTH:
  946. if (volMemMode == VOL_MEM_MODE_1LM) {
  947. return XSOCKET_DDRT_1LM_WRITE_BANDWIDTH;
  948. } else {
  949. return XSOCKET_DDRT_2LM_WRITE_BANDWIDTH;
  950. }
  951. default:
  952. return 0xFF;
  953. }
  954. } else if (Type == DDR2LMCACHE) {
  955. switch (DataType) {
  956. case EFI_ACPI_HMAT_ACCESS_BANDWIDTH:
  957. return DDR2LMCACHE_ACCESS_BANDWIDTH;
  958. case EFI_ACPI_HMAT_READ_BANDWIDTH:
  959. return DDR2LMCACHE_READ_BANDWIDTH;
  960. case EFI_ACPI_HMAT_WRITE_BANDWIDTH:
  961. return DDR2LMCACHE_WRITE_BANDWIDTH;
  962. default:
  963. return 0xFF;
  964. }
  965. } else {
  966. switch (DataType) {
  967. case EFI_ACPI_HMAT_ACCESS_BANDWIDTH:
  968. return XSOCKET_DDR_ACCESS_BANDWIDTH;
  969. case EFI_ACPI_HMAT_READ_BANDWIDTH:
  970. return XSOCKET_DDR_READ_BANDWIDTH;
  971. case EFI_ACPI_HMAT_WRITE_BANDWIDTH:
  972. return XSOCKET_DDR_WRITE_BANDWIDTH;
  973. default:
  974. return 0xFF;
  975. }
  976. }
  977. }
  978. /**
  979. Get the Read/Write/Access Latency value of the memory type.
  980. @param [in] DataType Type of latency value that is required (Read/Write/Access)
  981. @param [in] Type Type of memory for which Latency is required. (DDR/DDRT)
  982. @retval Value of the Latency associated with memory type.
  983. @retval 0xFF Input parameters are invalid.
  984. **/
  985. UINT16
  986. GetMemoryLatency (
  987. IN UINT8 DataType,
  988. IN MemoryType Type,
  989. IN UINT8 volMemMode
  990. )
  991. {
  992. if (Type == DDRT) { // MemoryType == DDRT
  993. switch (DataType) {
  994. case EFI_ACPI_HMAT_ACCESS_LATENCY :
  995. return DDRT_ACCESS_LATENCY;
  996. case EFI_ACPI_HMAT_READ_LATENCY :
  997. if (volMemMode == VOL_MEM_MODE_1LM) {
  998. return DDRT_1LM_READ_LATENCY;
  999. } else {
  1000. return DDRT_2LM_READ_LATENCY;
  1001. }
  1002. case EFI_ACPI_HMAT_WRITE_LATENCY :
  1003. if (volMemMode == VOL_MEM_MODE_1LM) {
  1004. return DDRT_1LM_WRITE_LATENCY;
  1005. } else {
  1006. return DDRT_2LM_WRITE_LATENCY;
  1007. }
  1008. default:
  1009. return 0xFF;
  1010. }
  1011. } else if (Type == DDR2LMCACHE){
  1012. switch (DataType) {
  1013. case EFI_ACPI_HMAT_ACCESS_LATENCY :
  1014. return DDR2LMCACHE_ACCESS_LATENCY;
  1015. case EFI_ACPI_HMAT_READ_LATENCY :
  1016. return DDR2LMCACHE_READ_LATENCY;
  1017. case EFI_ACPI_HMAT_WRITE_LATENCY :
  1018. return DDR2LMCACHE_WRITE_LATENCY;
  1019. default:
  1020. return 0xFF;
  1021. }
  1022. } else {
  1023. switch (DataType) {
  1024. case EFI_ACPI_HMAT_ACCESS_LATENCY :
  1025. return DDR_ACCESS_LATENCY;
  1026. case EFI_ACPI_HMAT_READ_LATENCY :
  1027. return DDR_READ_LATENCY;
  1028. case EFI_ACPI_HMAT_WRITE_LATENCY :
  1029. return DDR_WRITE_LATENCY;
  1030. default:
  1031. return 0xFF;
  1032. }
  1033. }
  1034. }
  1035. /**
  1036. Get the Read/Write/Access Latency value of the memory type between sockets.
  1037. @param [in] DataType Type of latency value that is required (Read/Write/Access)
  1038. @param [in] Type Type of memory for which Latency is required. (DDR/DDRT)
  1039. @retval Value of the Latency associated with memory type.
  1040. @retval 0xFF Input parameters are invalid.
  1041. **/
  1042. UINT16
  1043. GetXSocketMemoryLatency (
  1044. IN UINT8 DataType,
  1045. IN MemoryType Type,
  1046. IN UINT8 volMemMode
  1047. )
  1048. {
  1049. if (Type == DDRT) { // MemoryType == DDRT
  1050. switch (DataType) {
  1051. case EFI_ACPI_HMAT_ACCESS_LATENCY :
  1052. return DDRT_ACCESS_LATENCY;
  1053. case EFI_ACPI_HMAT_READ_LATENCY :
  1054. if (volMemMode == VOL_MEM_MODE_1LM) {
  1055. return XSOCKET_DDRT_1LM_READ_LATENCY;
  1056. } else {
  1057. return XSOCKET_DDRT_2LM_READ_LATENCY;
  1058. }
  1059. case EFI_ACPI_HMAT_WRITE_LATENCY :
  1060. if (volMemMode == VOL_MEM_MODE_1LM) {
  1061. return XSOCKET_DDRT_1LM_WRITE_LATENCY;
  1062. } else {
  1063. return XSOCKET_DDRT_2LM_WRITE_LATENCY;
  1064. }
  1065. default:
  1066. return 0xFF;
  1067. }
  1068. } else if (Type == DDR2LMCACHE){
  1069. switch (DataType) {
  1070. case EFI_ACPI_HMAT_ACCESS_LATENCY :
  1071. return DDR2LMCACHE_ACCESS_LATENCY;
  1072. case EFI_ACPI_HMAT_READ_LATENCY :
  1073. return DDR2LMCACHE_READ_LATENCY;
  1074. case EFI_ACPI_HMAT_WRITE_LATENCY :
  1075. return DDR2LMCACHE_WRITE_LATENCY;
  1076. default:
  1077. return 0xFF;
  1078. }
  1079. } else {
  1080. switch (DataType) {
  1081. case EFI_ACPI_HMAT_ACCESS_LATENCY :
  1082. return XSOCKET_DDR_ACCESS_LATENCY;
  1083. case EFI_ACPI_HMAT_READ_LATENCY :
  1084. return XSOCKET_DDR_READ_LATENCY;
  1085. case EFI_ACPI_HMAT_WRITE_LATENCY :
  1086. return XSOCKET_DDR_WRITE_LATENCY;
  1087. default:
  1088. return 0xFF;
  1089. }
  1090. }
  1091. }
  1092. /**
  1093. Patch HMAT LATENCY_BANDWIDTH_INFO_STRUCTURE structure.
  1094. @param [in] Lbis Points to HMAT LATENCY_BANDWIDTH_INFO_STRUCTURE to be modified
  1095. @param [in, out] LibsSlackSize Points to cummulative LIBS slack size
  1096. @param [in] HmatData HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE to be consumed
  1097. @retval None
  1098. **/
  1099. VOID
  1100. PatchBandWidthLbis (
  1101. IN LATENCY_BANDWIDTH_INFO_STRUCTURE **LbisPtr,
  1102. IN OUT UINTN *LibsSlackSize,
  1103. IN HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData,
  1104. IN UINT8 DataType,
  1105. IN MemoryType Type,
  1106. IN UINT8 volMemMode
  1107. )
  1108. {
  1109. UINT32 Row = 0;
  1110. UINT32 Col = 0;
  1111. UINT32 RowSocketId = 0;
  1112. UINT32 ColSocketId = 0;
  1113. UINT32 RowBaseIndex = 0;
  1114. UINT32 StructSize = 0;
  1115. UINT32 InitiatorIndex = 0;
  1116. UINT32 TargetIndex = 0;
  1117. LATENCY_BANDWIDTH_INFO_STRUCTURE *Lbis = *LbisPtr;
  1118. UINT32 *InitiatorProximityDomainList = (UINT32*)Lbis;
  1119. UINT32 *TargetProximityDomainList = (UINT32*)Lbis;
  1120. UINT16 *RelativeDistanceEntry = (UINT16*)Lbis;
  1121. Lbis->Type = SYSTEM_LOCALITY_LATENCY_BANDWIDTH_INFORMATION_STRUCTURE_TYPE;
  1122. Lbis->DataType = DataType;
  1123. Lbis->InitiatorProximityDomainsNumber = HmatData->ProcessorDomainNumber;
  1124. Lbis->TargetProximityDomainsNumber = HmatData->MemoryDomainNumber;
  1125. switch (Type) {
  1126. case DDR2LMCACHE:
  1127. Lbis->EntryBaseUnit = DDR2LMCACHE_BANDWIDTH_BASE_UNIT;
  1128. Lbis->Flags = EFI_ACPI_HMAT_MEMORY_HIERACHY_LAST_LEVEL_MEMORY;
  1129. break;
  1130. default:
  1131. Lbis->EntryBaseUnit = MEMORY_BANDWIDTH_BASE_UNIT;
  1132. Lbis->Flags = EFI_ACPI_HMAT_MEMORY_HIERACHY_MEMORY;
  1133. }
  1134. InitiatorProximityDomainList = (UINT32*)&(Lbis->InitiatorProximityDomainList[0]);
  1135. StructSize = (UINT32)((UINT8*)InitiatorProximityDomainList - (UINT8*)Lbis);
  1136. StructSize += (Lbis->InitiatorProximityDomainsNumber * (sizeof (UINT32)));
  1137. TargetProximityDomainList = (UINT32*)((UINT8*)TargetProximityDomainList + StructSize);
  1138. StructSize += (Lbis->TargetProximityDomainsNumber * (sizeof (UINT32)));
  1139. RelativeDistanceEntry = (UINT16*)((UINT8*)RelativeDistanceEntry + StructSize);
  1140. StructSize += (Lbis->InitiatorProximityDomainsNumber * Lbis->TargetProximityDomainsNumber * (sizeof (UINT16)));
  1141. Lbis->Length = StructSize;
  1142. for (Row = 0; Row < Lbis->InitiatorProximityDomainsNumber; Row++) {
  1143. *(InitiatorProximityDomainList + Row) = Row;
  1144. }
  1145. for (Row = 0; Row < Lbis->TargetProximityDomainsNumber; Row++) {
  1146. *(TargetProximityDomainList + Row) = Row;
  1147. }
  1148. Row = 0;
  1149. for (InitiatorIndex = 0; InitiatorIndex < EFI_ACPI_HMAT_NUMBER_OF_PROCESSOR_DOMAINS; InitiatorIndex++) {
  1150. if (HmatData->ProcessorDomainList[InitiatorIndex] == 1) {
  1151. RowSocketId = HmatData->ProcessorDomainSocketIdList[InitiatorIndex];
  1152. RowBaseIndex = Row * Lbis->TargetProximityDomainsNumber;
  1153. Col = 0;
  1154. for (TargetIndex = 0; TargetIndex < EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS; TargetIndex++) {
  1155. if (HmatData->MemoryDomainList[TargetIndex].Valid == 1) {
  1156. ColSocketId = HmatData->MemoryDomainList[TargetIndex].PhysicalSocketId;
  1157. if (Type == DDR2LMCACHE) {
  1158. //
  1159. // DDR acting as cache for DDRT
  1160. //SocketsLinked
  1161. //
  1162. if (SocketsLinked (RowSocketId, ColSocketId)) {
  1163. RelativeDistanceEntry[RowBaseIndex + Col] = GetXSocketMemoryBandWidth (DataType, Type, volMemMode);
  1164. } else {
  1165. RelativeDistanceEntry[RowBaseIndex + Col] = GetMemoryBandWidth (DataType, Type, volMemMode);
  1166. }
  1167. } else if (mSystemMemoryMap->volMemMode == VOL_MEM_MODE_2LM) {
  1168. //
  1169. // Add only details for DDRT as entire DDR is acting as Cache
  1170. //
  1171. if (SocketsLinked (RowSocketId, ColSocketId)) {
  1172. RelativeDistanceEntry[RowBaseIndex + Col] = GetXSocketMemoryBandWidth (DataType, DDRT, volMemMode);
  1173. } else {
  1174. RelativeDistanceEntry[RowBaseIndex + Col] = GetMemoryBandWidth (DataType, DDRT, volMemMode);
  1175. }
  1176. } else {
  1177. //
  1178. // Neither cache nor 2LM, we need to add details for both DDR and DDRT
  1179. //
  1180. if ((Col / (HmatData->MemoryDomainNumber- SkippedEntries)) == 0) {
  1181. //
  1182. // DDR entries
  1183. //
  1184. if (SocketsLinked (RowSocketId, ColSocketId)) {
  1185. RelativeDistanceEntry[RowBaseIndex + Col] = GetXSocketMemoryBandWidth (DataType, DDR, volMemMode);
  1186. } else {
  1187. RelativeDistanceEntry[RowBaseIndex + Col] = GetMemoryBandWidth (DataType, DDR, volMemMode);
  1188. }
  1189. } else {
  1190. //
  1191. // DDRT entries
  1192. //
  1193. if (SocketsLinked (RowSocketId, ColSocketId)) {
  1194. RelativeDistanceEntry[RowBaseIndex + Col] = GetXSocketMemoryBandWidth (DataType, DDRT, volMemMode);
  1195. } else {
  1196. RelativeDistanceEntry[RowBaseIndex + Col] = GetMemoryBandWidth (DataType, DDRT, volMemMode);
  1197. }
  1198. }
  1199. }
  1200. Col++;
  1201. } //if (HmatData->MemoryDomainList[TargetIndex].Valid == 1)
  1202. } // for (TargetIndex)
  1203. Row++;
  1204. } // if (HmatData->ProcessorDomainList[InitiatorIndex] == 1)
  1205. } //for (InitiatorIndex)
  1206. *LibsSlackSize += StructSize;
  1207. *LbisPtr = (LATENCY_BANDWIDTH_INFO_STRUCTURE *)((UINT8*)Lbis + StructSize);
  1208. }
  1209. /**
  1210. Patch HMAT LATENCY_BANDWIDTH_INFO_STRUCTURE structure.
  1211. @param [in] Lbis Points to HMAT LATENCY_BANDWIDTH_INFO_STRUCTURE to be modified
  1212. @param [in, out] LibsSlackSize Points to cumulative LIBS slack size
  1213. @param [in] HmatData HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE to be consumed
  1214. @retval None
  1215. **/
  1216. VOID
  1217. PatchMemoryLatencyLbis (
  1218. IN LATENCY_BANDWIDTH_INFO_STRUCTURE **LbisPtr,
  1219. IN OUT UINTN *LibsSlackSize,
  1220. IN HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData,
  1221. IN UINT8 DataType,
  1222. IN MemoryType Type,
  1223. IN UINT8 volMemMode
  1224. )
  1225. {
  1226. UINT32 Row = 0;
  1227. UINT32 Col = 0;
  1228. UINT32 RowSocketId = 0;
  1229. UINT32 ColSocketId = 0;
  1230. UINT32 RowBaseIndex = 0;
  1231. UINT32 StructSize = 0;
  1232. UINT32 InitiatorIndex = 0;
  1233. UINT32 TargetIndex = 0;
  1234. LATENCY_BANDWIDTH_INFO_STRUCTURE *Lbis = *LbisPtr;
  1235. UINT32 *InitiatorProximityDomainList = (UINT32*)Lbis;
  1236. UINT32 *TargetProximityDomainList = (UINT32*)Lbis;
  1237. UINT16 *RelativeDistanceEntry = (UINT16*)Lbis;
  1238. Lbis->Type = SYSTEM_LOCALITY_LATENCY_BANDWIDTH_INFORMATION_STRUCTURE_TYPE;
  1239. Lbis->DataType = DataType;
  1240. Lbis->InitiatorProximityDomainsNumber = HmatData->ProcessorDomainNumber;
  1241. Lbis->TargetProximityDomainsNumber = HmatData->MemoryDomainNumber;
  1242. switch (Type) {
  1243. case DDR2LMCACHE:
  1244. Lbis->EntryBaseUnit = DDR2LMCACHE_BANDWIDTH_BASE_UNIT;
  1245. Lbis->Flags = EFI_ACPI_HMAT_MEMORY_HIERACHY_LAST_LEVEL_MEMORY;
  1246. break;
  1247. default:
  1248. Lbis->EntryBaseUnit = MEMORY_LATENCY_BASE_UNIT;
  1249. Lbis->Flags = EFI_ACPI_HMAT_MEMORY_HIERACHY_MEMORY;
  1250. }
  1251. InitiatorProximityDomainList = (UINT32*)&(Lbis->InitiatorProximityDomainList[0]);
  1252. StructSize = (UINT32)((UINT8*)InitiatorProximityDomainList - (UINT8*)Lbis);
  1253. StructSize += (Lbis->InitiatorProximityDomainsNumber * (sizeof (UINT32)));
  1254. TargetProximityDomainList = (UINT32*)((UINT8*)TargetProximityDomainList + StructSize);
  1255. StructSize += (Lbis->TargetProximityDomainsNumber * (sizeof (UINT32)));
  1256. RelativeDistanceEntry = (UINT16*)((UINT8*)RelativeDistanceEntry + StructSize);
  1257. StructSize += (Lbis->InitiatorProximityDomainsNumber * Lbis->TargetProximityDomainsNumber * (sizeof (UINT16)));
  1258. Lbis->Length = StructSize;
  1259. for (Row = 0; Row < Lbis->InitiatorProximityDomainsNumber; Row++) {
  1260. *(InitiatorProximityDomainList + Row) = Row;
  1261. }
  1262. for (Row = 0; Row < Lbis->TargetProximityDomainsNumber; Row++) {
  1263. *(TargetProximityDomainList + Row) = Row;
  1264. }
  1265. Row = 0;
  1266. for (InitiatorIndex = 0; InitiatorIndex < EFI_ACPI_HMAT_NUMBER_OF_PROCESSOR_DOMAINS; InitiatorIndex++) {
  1267. if (HmatData->ProcessorDomainList[InitiatorIndex] == 1) {
  1268. RowSocketId = HmatData->ProcessorDomainSocketIdList[InitiatorIndex];
  1269. RowBaseIndex = Row * Lbis->TargetProximityDomainsNumber;
  1270. Col = 0;
  1271. for (TargetIndex = 0; TargetIndex < EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS; TargetIndex++) {
  1272. if (HmatData->MemoryDomainList[TargetIndex].Valid == 1) {
  1273. ColSocketId = HmatData->MemoryDomainList[TargetIndex].PhysicalSocketId;
  1274. if (Type == DDR2LMCACHE) {
  1275. //
  1276. // DDR acting as cache for DDRT
  1277. //
  1278. if (SocketsLinked (RowSocketId, ColSocketId)) {
  1279. RelativeDistanceEntry[RowBaseIndex + Col] = GetXSocketMemoryLatency (DataType, Type, volMemMode);
  1280. } else {
  1281. RelativeDistanceEntry[RowBaseIndex + Col] = GetMemoryLatency (DataType, Type, volMemMode);
  1282. }
  1283. } else if (mSystemMemoryMap->volMemMode == VOL_MEM_MODE_2LM) {
  1284. //
  1285. // Add only details for DDRT as entire DDR is acting as Cache
  1286. //
  1287. if (SocketsLinked (RowSocketId, ColSocketId)) {
  1288. RelativeDistanceEntry[RowBaseIndex + Col] = GetXSocketMemoryLatency (DataType, DDRT, volMemMode);
  1289. } else {
  1290. RelativeDistanceEntry[RowBaseIndex + Col] = GetMemoryLatency (DataType, DDRT, volMemMode);
  1291. }
  1292. } else {
  1293. //
  1294. // Neither cache nor 2LM, we need to add details for both DDR and DDRT
  1295. //
  1296. if ((Col / (HmatData->MemoryDomainNumber - SkippedEntries)) == 0) {
  1297. //
  1298. // DDR entries
  1299. //
  1300. if (SocketsLinked (RowSocketId, ColSocketId)) {
  1301. RelativeDistanceEntry[RowBaseIndex + Col] = GetXSocketMemoryLatency (DataType, DDR, volMemMode);
  1302. } else {
  1303. RelativeDistanceEntry[RowBaseIndex + Col] = GetMemoryLatency (DataType, DDR, volMemMode);
  1304. }
  1305. } else {
  1306. //
  1307. // DDRT entries
  1308. //
  1309. if (SocketsLinked (RowSocketId, ColSocketId)) {
  1310. RelativeDistanceEntry[RowBaseIndex + Col] = GetXSocketMemoryLatency (DataType, DDRT, volMemMode);
  1311. } else {
  1312. RelativeDistanceEntry[RowBaseIndex + Col] = GetMemoryLatency (DataType, DDRT, volMemMode);
  1313. }
  1314. }
  1315. }
  1316. Col++;
  1317. } //if (HmatData->MemoryDomainList[TargetIndex].Valid == 1)
  1318. } // for (TargetIndex)
  1319. Row++;
  1320. } // if (HmatData->ProcessorDomainList[InitiatorIndex] == 1)
  1321. } //for (InitiatorIndex)
  1322. *LibsSlackSize += StructSize;
  1323. *LbisPtr = (LATENCY_BANDWIDTH_INFO_STRUCTURE *)((UINT8*)Lbis + StructSize);
  1324. }
  1325. /**
  1326. Patch HMAT LATENCY_BANDWIDTH_INFO_STRUCTURE structure.
  1327. @param [in] Lbis Points to HMAT LATENCY_BANDWIDTH_INFO_STRUCTURE to be modified
  1328. @param [in, out] SlackSize Points to cummulative slack size
  1329. @param [in] HmatData HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE to be consumed
  1330. @retval None
  1331. **/
  1332. VOID
  1333. PatchHmatLbis (
  1334. IN LATENCY_BANDWIDTH_INFO_STRUCTURE *Lbis,
  1335. IN OUT UINTN *SlackSize,
  1336. IN HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData
  1337. )
  1338. {
  1339. UINTN LibsStructSize=0;
  1340. UINT8 volMemMode;
  1341. LATENCY_BANDWIDTH_INFO_STRUCTURE *OrginalLbis = Lbis;
  1342. volMemMode = mSystemMemoryMap->volMemMode;
  1343. DEBUG ((DEBUG_INFO, "[ACPI] (HMAT) Populating System Locality Latency and Bandwidth Information Structure\n"));
  1344. PatchMemoryLatencyLbis (&Lbis, &LibsStructSize, HmatData, EFI_ACPI_HMAT_READ_LATENCY, DDR, volMemMode);
  1345. PatchMemoryLatencyLbis (&Lbis, &LibsStructSize, HmatData, EFI_ACPI_HMAT_WRITE_LATENCY, DDR, volMemMode);
  1346. PatchBandWidthLbis (&Lbis, &LibsStructSize, HmatData, EFI_ACPI_HMAT_READ_BANDWIDTH, DDR, volMemMode);
  1347. PatchBandWidthLbis (&Lbis, &LibsStructSize, HmatData, EFI_ACPI_HMAT_WRITE_BANDWIDTH, DDR, volMemMode);
  1348. if (mSystemMemoryMap->volMemMode != VOL_MEM_MODE_1LM) {
  1349. PatchMemoryLatencyLbis (&Lbis, &LibsStructSize, HmatData, EFI_ACPI_HMAT_READ_LATENCY, DDR2LMCACHE, volMemMode);
  1350. PatchMemoryLatencyLbis (&Lbis, &LibsStructSize, HmatData, EFI_ACPI_HMAT_WRITE_LATENCY, DDR2LMCACHE, volMemMode);
  1351. PatchBandWidthLbis (&Lbis, &LibsStructSize, HmatData, EFI_ACPI_HMAT_READ_BANDWIDTH, DDR2LMCACHE, volMemMode);
  1352. PatchBandWidthLbis (&Lbis, &LibsStructSize, HmatData, EFI_ACPI_HMAT_WRITE_BANDWIDTH, DDR2LMCACHE, volMemMode);
  1353. }
  1354. RemoveSlack (SlackSize, OrginalLbis, LibsStructSize);
  1355. *SlackSize += EFI_ACPI_HMAT_LBIS_COUNT * sizeof(Lbis[0]) - LibsStructSize;
  1356. }
  1357. /**
  1358. Get Type 17 Handles for HBM devices used as cache.
  1359. @param [in, out] SmbiosHandles Points to SmbiosHandles array to be modified
  1360. @param [in] NumaNode Value for NUMA Node whose memory is being cached for the specific HBM devices
  1361. @retval None
  1362. **/
  1363. VOID
  1364. GetHbmCacheHandles (
  1365. IN UINT16 *SmbiosHandles,
  1366. IN UINT8 NumaNode
  1367. )
  1368. {
  1369. EFI_STATUS Status = EFI_SUCCESS;
  1370. SMBIOS_TABLE_TYPE17 *SmbiosType17Record;
  1371. EFI_SMBIOS_HANDLE SmbiosHandle = 0;
  1372. EFI_SMBIOS_PROTOCOL *mSmbios;
  1373. EFI_SMBIOS_TYPE SmbiosType = EFI_SMBIOS_TYPE_MEMORY_DEVICE;
  1374. EFI_SMBIOS_TABLE_HEADER *SmbiosRecord;
  1375. UINT8 HbmHandleCount = 0;
  1376. Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **) &mSmbios);
  1377. if (!(EFI_ERROR (Status))) {
  1378. while ((!(EFI_ERROR (Status))) && (SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED) ){
  1379. Status = mSmbios->GetNext (mSmbios, &SmbiosHandle, &SmbiosType, &SmbiosRecord, NULL);
  1380. SmbiosType17Record = (SMBIOS_TABLE_TYPE17 *) SmbiosRecord;
  1381. if ((SmbiosType17Record->TypeDetail.CacheDram == 1) && (SmbiosType17Record->DeviceSet == NumaNode) ) {
  1382. SmbiosHandles[HbmHandleCount] = SmbiosType17Record->Hdr.Handle;
  1383. HbmHandleCount++;
  1384. }
  1385. }
  1386. }
  1387. }
  1388. /**
  1389. Patch HMAT MEMORY_SIDE_CACHE_INFORMATION_STRUCTURE substructure.
  1390. @param [in, out] Mscis Points to HMAT MEMORY_SIDE_CACHE_INFORMATION_STRUCTURE to be modified
  1391. @param [in, out] SlackSize Points to cumulative slack size
  1392. @param [in] HmatData HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE to be consumed
  1393. @retval None
  1394. **/
  1395. VOID
  1396. PatchHmatMscis (
  1397. IN OUT MEMORY_SIDE_CACHE_INFORMATION_STRUCTURE *Mscis,
  1398. IN OUT UINTN *SlackSize,
  1399. IN HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData
  1400. )
  1401. {
  1402. UINT32 Index;
  1403. UINT32 Count = 0;
  1404. UINT32 UnusedCount;
  1405. UINT8 SmbiosHandleIndex;
  1406. DEBUG ((DEBUG_INFO, "[ACPI] (HMAT) Populating Memory Side Cache Information Structure\n"));
  1407. for (Index = 0; Index < EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS; Index++) {
  1408. if ((HmatData->MemoryDomainList[Index].Valid == 0) || (HmatData->MemoryDomainList[Index].Cacheable == 0)) {
  1409. continue;
  1410. }
  1411. //
  1412. // Fill in fields for Cached Memory Domains
  1413. //
  1414. Mscis[Count].MemoryProximityDomain = Index;
  1415. Mscis[Count].CacheAttributes.Bits.TotalCacheLevels = EFI_ACPI_HMAT_ONE_LEVEL_CACHE;
  1416. Mscis[Count].CacheAttributes.Bits.CacheLevel = EFI_ACPI_HMAT_ONE_LEVEL_CACHE;
  1417. Mscis[Count].CacheAttributes.Bits.CacheLineSize = DDR4_CACHE_LINE_SIZE;
  1418. Mscis[Count].CacheAttributes.Bits.CacheAssociativity = EFI_ACPI_HMAT_CACHE_ASSOCIATIVITY_DIRECT_MAPPED;
  1419. Mscis[Count].CacheAttributes.Bits.WritePolicy = EFI_ACPI_HMAT_WRITE_POLICY_WB;
  1420. Mscis[Count].MemorySideCacheSize = LShiftU64 (HmatData->MemoryDomainList[Index].MemorySideCacheSize, MEM_ADDR_SHFT_VAL);
  1421. Mscis[Count].NumSmbiosHandles = HmatData->MemoryDomainList[Index].NumSmbiosHandles;
  1422. for(SmbiosHandleIndex = 0 ; SmbiosHandleIndex < HmatData->MemoryDomainList[Index].NumSmbiosHandles; SmbiosHandleIndex++){
  1423. Mscis[Count].SmbiosHandles[SmbiosHandleIndex] = HmatData->MemoryDomainList[Index].SmbiosHandles[SmbiosHandleIndex];
  1424. }
  1425. DEBUG ((DEBUG_INFO, "[ACPI] (HMAT) MSCIS[%x] MemorySideCacheSize = 0x%lx, ProximityDomain = %x\n", Count, Mscis[Count].MemorySideCacheSize, Index));
  1426. Count++;
  1427. }
  1428. //
  1429. // Move MSCIS entries up to replace removed MSARS entries
  1430. //
  1431. if (*SlackSize && Count) {
  1432. RemoveSlack (SlackSize, Mscis, Count * sizeof(Mscis[0]));
  1433. }
  1434. //
  1435. // Update SlackSize for unused MSCIS entries
  1436. //
  1437. UnusedCount = EFI_ACPI_HMAT_MSCIS_COUNT - Count;
  1438. *SlackSize += UnusedCount * sizeof(Mscis[0]);
  1439. }
  1440. /**
  1441. Update the HMAT table.
  1442. @param [in, out] HmatAcpiTable The table to be set.
  1443. @retval EFI SUCCESS Procedure returned successfully.
  1444. **/
  1445. EFI_STATUS
  1446. PatchHmatAcpiTable (
  1447. IN OUT EFI_ACPI_COMMON_HEADER *Table
  1448. )
  1449. {
  1450. UINTN SlackSize = 0;
  1451. HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData = NULL;
  1452. EFI_ACPI_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE *HmatAcpiTable;
  1453. if (mSystemMemoryMap == NULL) {
  1454. ASSERT (FALSE);
  1455. return EFI_UNSUPPORTED;
  1456. }
  1457. HmatAcpiTable = (EFI_ACPI_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE *)Table;
  1458. HmatData = (HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *) InitializeHmatData ();
  1459. if (HmatData == NULL) {
  1460. DEBUG ((DEBUG_ERROR, "ACPI (HMAT) HMAT Data could not be initialized... skipping HMAT Patch\n"));
  1461. return EFI_OUT_OF_RESOURCES;
  1462. }
  1463. //
  1464. // Patch the MSARS, SLLBIS, and MSCIS Structure from HMAT Table.
  1465. //
  1466. PatchHmatMsars (HmatAcpiTable, &SlackSize, HmatData);
  1467. PatchHmatLbis (HmatAcpiTable->Lbis, &SlackSize, HmatData);
  1468. PatchHmatMscis (HmatAcpiTable->MemSideCache, &SlackSize, HmatData);
  1469. if (HmatData != NULL) {
  1470. FreePool (HmatData);
  1471. }
  1472. //
  1473. // Update HMAT table size
  1474. //
  1475. HmatAcpiTable->HmatHeader.Header.Length -= (UINT32)SlackSize;
  1476. //
  1477. // Dump HMAT
  1478. //
  1479. DumpHmat (HmatAcpiTable);
  1480. return EFI_SUCCESS;
  1481. }