AcpiPptt.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /** @file
  2. Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. **/
  5. #include <IndustryStandard/ArmCache.h>
  6. #include <Library/ArmLib.h>
  7. #include "AcpiPlatform.h"
  8. EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR PPTTProcessorTemplate = {
  9. EFI_ACPI_6_3_PPTT_TYPE_PROCESSOR,
  10. sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR),
  11. { EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE },
  12. {0}, /* Flags */
  13. 0, /* Parent */
  14. 0, /* AcpiProcessorId */
  15. 0 /* NumberOfPrivateResources */
  16. };
  17. EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE PPTTCacheTemplate = {
  18. EFI_ACPI_6_3_PPTT_TYPE_CACHE,
  19. sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE),
  20. { EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE },
  21. {0}, /* Flags */
  22. 0, /* NextLevelOfCache */
  23. 0, /* Size */
  24. 0, /* NumberOfSets */
  25. 0, /* Associativity */
  26. {0}, /* Attributes */
  27. 0
  28. };
  29. EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER PPTTTableHeaderTemplate = {
  30. __ACPI_HEADER (
  31. EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_STRUCTURE_SIGNATURE,
  32. 0, /* need fill in */
  33. EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_REVISION
  34. ),
  35. };
  36. STATIC EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER *PpttTablePointer;
  37. STATIC UINT32 PpttClusterOffset[PLATFORM_CPU_MAX_CPM * PLATFORM_CPU_MAX_SOCKET];
  38. STATIC UINT32 PpttSocketOffset[PLATFORM_CPU_MAX_SOCKET];
  39. STATIC UINT32 PpttRootOffset;
  40. STATIC UINT32 PpttL1DataCacheOffset[PLATFORM_CPU_MAX_NUM_CORES];
  41. STATIC UINT32 PpttL1InstructionCacheOffset[PLATFORM_CPU_MAX_NUM_CORES];
  42. STATIC UINT32 PpttL2CacheOffset[PLATFORM_CPU_MAX_NUM_CORES];
  43. UINT32
  44. AcpiPpttProcessorCoreNode (
  45. VOID *EntryPointer,
  46. UINT32 CpuId
  47. )
  48. {
  49. EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR *PpttProcessorEntryPointer = EntryPointer;
  50. UINT32 *ResPointer;
  51. UINTN ClusterIdPerSocket, CoreIdPerCpm, SocketId;
  52. CopyMem (
  53. PpttProcessorEntryPointer,
  54. &PPTTProcessorTemplate,
  55. sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR)
  56. );
  57. ClusterIdPerSocket = (CpuId / PLATFORM_CPU_NUM_CORES_PER_CPM) % PLATFORM_CPU_MAX_CPM;
  58. SocketId = (CpuId / PLATFORM_CPU_NUM_CORES_PER_CPM) / PLATFORM_CPU_MAX_CPM;
  59. CoreIdPerCpm = CpuId % PLATFORM_CPU_NUM_CORES_PER_CPM;
  60. PpttProcessorEntryPointer->Flags.AcpiProcessorIdValid = 1;
  61. PpttProcessorEntryPointer->Flags.NodeIsALeaf = 1;
  62. PpttProcessorEntryPointer->Flags.IdenticalImplementation = 1;
  63. PpttProcessorEntryPointer->AcpiProcessorId = (SocketId << PLATFORM_SOCKET_UID_BIT_OFFSET) | (ClusterIdPerSocket << 8) | CoreIdPerCpm;
  64. PpttProcessorEntryPointer->Parent = (UINT32)PpttClusterOffset[CpuId / PLATFORM_CPU_NUM_CORES_PER_CPM];
  65. PpttProcessorEntryPointer->NumberOfPrivateResources = 2; /* L1I + L1D */
  66. ResPointer = (UINT32 *)((UINT64)EntryPointer +
  67. sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR));
  68. ResPointer[0] = PpttL1InstructionCacheOffset[CpuId];
  69. ResPointer[1] = PpttL1DataCacheOffset[CpuId];
  70. PpttProcessorEntryPointer->Length = sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR) + 2 * sizeof (UINT32);
  71. return PpttProcessorEntryPointer->Length;
  72. }
  73. STATIC UINT32
  74. AcpiPpttClusterNode (
  75. VOID *EntryPointer,
  76. UINT32 ClusterId
  77. )
  78. {
  79. EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR *PpttProcessorEntryPointer = EntryPointer;
  80. PpttClusterOffset[ClusterId] = (UINT64)EntryPointer - (UINT64)PpttTablePointer;
  81. CopyMem (
  82. PpttProcessorEntryPointer,
  83. &PPTTProcessorTemplate,
  84. sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR)
  85. );
  86. PpttProcessorEntryPointer->Parent = (UINT32)PpttSocketOffset[ClusterId / PLATFORM_CPU_MAX_CPM];
  87. PpttProcessorEntryPointer->Flags.IdenticalImplementation = 1;
  88. return PpttProcessorEntryPointer->Length;
  89. }
  90. STATIC UINT32
  91. AcpiPpttSocketNode (
  92. VOID *EntryPointer,
  93. UINT32 SocketId
  94. )
  95. {
  96. EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR *PpttProcessorEntryPointer = EntryPointer;
  97. PpttSocketOffset[SocketId] = (UINT64)EntryPointer - (UINT64)PpttTablePointer;
  98. CopyMem (
  99. PpttProcessorEntryPointer,
  100. &PPTTProcessorTemplate,
  101. sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR)
  102. );
  103. PpttProcessorEntryPointer->Flags.PhysicalPackage = 1;
  104. PpttProcessorEntryPointer->Flags.IdenticalImplementation = 1;
  105. PpttProcessorEntryPointer->Parent = (UINT32)PpttRootOffset;
  106. return PpttProcessorEntryPointer->Length;
  107. }
  108. STATIC UINT32
  109. AcpiPpttRootNode (
  110. VOID *EntryPointer
  111. )
  112. {
  113. EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR *PpttProcessorEntryPointer = EntryPointer;
  114. PpttRootOffset = (UINT64)EntryPointer - (UINT64)PpttTablePointer;
  115. CopyMem (
  116. PpttProcessorEntryPointer,
  117. &PPTTProcessorTemplate,
  118. sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR)
  119. );
  120. PpttProcessorEntryPointer->Flags.IdenticalImplementation = 1;
  121. return PpttProcessorEntryPointer->Length;
  122. }
  123. STATIC VOID
  124. AcpiPpttFillCacheSizeInfo (
  125. EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE *Node,
  126. UINT32 Level,
  127. BOOLEAN DataCache,
  128. BOOLEAN UnifiedCache
  129. )
  130. {
  131. CSSELR_DATA CsselrData;
  132. CCSIDR_DATA CcsidrData;
  133. CsselrData.Data = 0;
  134. CsselrData.Bits.Level = Level - 1;
  135. CsselrData.Bits.InD = (!DataCache && !UnifiedCache);
  136. CcsidrData.Data = ReadCCSIDR (CsselrData.Data);
  137. Node->Flags.LineSizeValid = 1;
  138. Node->Flags.NumberOfSetsValid = 1;
  139. Node->Flags.AssociativityValid = 1;
  140. Node->Flags.SizePropertyValid = 1;
  141. Node->Flags.CacheTypeValid = 1;
  142. Node->NumberOfSets = (UINT16)CcsidrData.BitsNonCcidx.NumSets + 1;
  143. Node->Associativity = (UINT16)CcsidrData.BitsNonCcidx.Associativity + 1;
  144. Node->LineSize = (UINT16)(1 << (CcsidrData.BitsNonCcidx.LineSize + 4));;
  145. Node->Size = Node->NumberOfSets *
  146. Node->Associativity *
  147. Node->LineSize;
  148. }
  149. STATIC UINT32
  150. AcpiPpttL1DataCacheNode (
  151. VOID *EntryPointer,
  152. UINT32 CpuId
  153. )
  154. {
  155. EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE *PpttCacheEntryPointer = EntryPointer;
  156. PpttL1DataCacheOffset[CpuId] = (UINT64)EntryPointer - (UINT64)PpttTablePointer;
  157. CopyMem (
  158. PpttCacheEntryPointer,
  159. &PPTTCacheTemplate,
  160. sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE)
  161. );
  162. AcpiPpttFillCacheSizeInfo (PpttCacheEntryPointer, 1, TRUE, FALSE);
  163. PpttCacheEntryPointer->Attributes.CacheType = 0x0; /* Data Cache */
  164. PpttCacheEntryPointer->NextLevelOfCache = PpttL2CacheOffset[CpuId];
  165. return PpttCacheEntryPointer->Length;
  166. }
  167. STATIC UINT32
  168. AcpiPpttL1InstructionCacheNode (
  169. VOID *EntryPointer,
  170. UINT32 CpuId
  171. )
  172. {
  173. EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE *PpttCacheEntryPointer = EntryPointer;
  174. PpttL1InstructionCacheOffset[CpuId] = (UINT64)EntryPointer - (UINT64)PpttTablePointer;
  175. CopyMem (
  176. PpttCacheEntryPointer,
  177. &PPTTCacheTemplate,
  178. sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE)
  179. );
  180. AcpiPpttFillCacheSizeInfo (PpttCacheEntryPointer, 1, FALSE, FALSE);
  181. PpttCacheEntryPointer->Attributes.CacheType = 0x1; /* Instruction Cache */
  182. PpttCacheEntryPointer->NextLevelOfCache = PpttL2CacheOffset[CpuId];
  183. return PpttCacheEntryPointer->Length;
  184. }
  185. STATIC UINT32
  186. AcpiPpttL2CacheNode (
  187. VOID *EntryPointer,
  188. UINT32 CpuId
  189. )
  190. {
  191. EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE *PpttCacheEntryPointer = EntryPointer;
  192. PpttL2CacheOffset[CpuId] = (UINT64)EntryPointer - (UINT64)PpttTablePointer;
  193. CopyMem (
  194. PpttCacheEntryPointer,
  195. &PPTTCacheTemplate,
  196. sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE)
  197. );
  198. AcpiPpttFillCacheSizeInfo (PpttCacheEntryPointer, 2, FALSE, TRUE);
  199. PpttCacheEntryPointer->Attributes.CacheType = 0x3; /* Unified Cache */
  200. PpttCacheEntryPointer->NextLevelOfCache = 0;
  201. return PpttCacheEntryPointer->Length;
  202. }
  203. /*
  204. * Install PPTT table.
  205. */
  206. EFI_STATUS
  207. AcpiInstallPpttTable (
  208. VOID
  209. )
  210. {
  211. EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR *PpttProcessorEntryPointer = NULL;
  212. EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
  213. UINTN PpttTableKey = 0;
  214. INTN Count;
  215. EFI_STATUS Status;
  216. UINTN Size;
  217. Status = gBS->LocateProtocol (
  218. &gEfiAcpiTableProtocolGuid,
  219. NULL,
  220. (VOID **)&AcpiTableProtocol
  221. );
  222. if (EFI_ERROR (Status)) {
  223. return Status;
  224. }
  225. Size = sizeof (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER) +
  226. sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR) + /* Root node */
  227. (PLATFORM_CPU_MAX_SOCKET * sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR)) + /* Socket node */
  228. (PLATFORM_CPU_MAX_CPM * PLATFORM_CPU_MAX_SOCKET * sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR)) + /* Cluster node */
  229. (PLATFORM_CPU_MAX_NUM_CORES * (sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR) + 2 * sizeof (UINT32))) + /* Core node */
  230. (PLATFORM_CPU_MAX_NUM_CORES * sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE)) + /* L1I node */
  231. (PLATFORM_CPU_MAX_NUM_CORES * sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE)) + /* L1D node */
  232. (PLATFORM_CPU_MAX_NUM_CORES * sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE)); /* L2 node */
  233. PpttTablePointer =
  234. (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER *)AllocateZeroPool (Size);
  235. if (PpttTablePointer == NULL) {
  236. return EFI_OUT_OF_RESOURCES;
  237. }
  238. PpttProcessorEntryPointer =
  239. (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR *)((UINT64)PpttTablePointer +
  240. sizeof (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER));
  241. Size = 0;
  242. Size += AcpiPpttRootNode ((VOID *)((UINT64)PpttProcessorEntryPointer + Size));
  243. for (Count = 0; Count < PLATFORM_CPU_MAX_SOCKET; Count++) {
  244. Size += AcpiPpttSocketNode ((VOID *)((UINT64)PpttProcessorEntryPointer + Size), Count);
  245. }
  246. for (Count = 0; Count < PLATFORM_CPU_MAX_CPM * PLATFORM_CPU_MAX_SOCKET; Count++) {
  247. Size += AcpiPpttClusterNode ((VOID *)((UINT64)PpttProcessorEntryPointer + Size), Count);
  248. }
  249. for (Count = 0; Count < PLATFORM_CPU_MAX_NUM_CORES; Count++) {
  250. Size += AcpiPpttL2CacheNode ((VOID *)((UINT64)PpttProcessorEntryPointer + Size), Count);
  251. Size += AcpiPpttL1InstructionCacheNode ((VOID *)((UINT64)PpttProcessorEntryPointer + Size), Count);
  252. Size += AcpiPpttL1DataCacheNode ((VOID *)((UINT64)PpttProcessorEntryPointer + Size), Count);
  253. Size += AcpiPpttProcessorCoreNode ((VOID *)((UINT64)PpttProcessorEntryPointer + Size), Count);
  254. }
  255. CopyMem (
  256. PpttTablePointer,
  257. &PPTTTableHeaderTemplate,
  258. sizeof (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER)
  259. );
  260. Size += sizeof (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER);
  261. PpttTablePointer->Header.Length = Size;
  262. AcpiUpdateChecksum ((UINT8 *)PpttTablePointer, PpttTablePointer->Header.Length);
  263. Status = AcpiTableProtocol->InstallAcpiTable (
  264. AcpiTableProtocol,
  265. (VOID *)PpttTablePointer,
  266. PpttTablePointer->Header.Length,
  267. &PpttTableKey
  268. );
  269. FreePool ((VOID *)PpttTablePointer);
  270. if (EFI_ERROR (Status)) {
  271. return Status;
  272. }
  273. return EFI_SUCCESS;
  274. }