Madt.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /** @file
  2. Multiple APIC Description Table (MADT)
  3. Copyright (c) 2012 - 2014, ARM Ltd. All rights reserved.<BR>
  4. Copyright (c) 2014 - 2016, AMD Inc. All rights reserved.<BR>
  5. This program and the accompanying materials
  6. are licensed and made available under the terms and conditions of the BSD License
  7. which accompanies this distribution. The full text of the license may be found at
  8. http://opensource.org/licenses/bsd-license.php
  9. THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  11. **/
  12. /**
  13. Derived from:
  14. ArmPlatformPkg/ArmJunoPkg/AcpiTables/Madt.aslc
  15. **/
  16. #include <Uefi.h>
  17. #include <Library/ArmLib.h>
  18. #include <Library/DebugLib.h>
  19. #include <Library/UefiBootServicesTableLib.h>
  20. #include <Guid/ArmMpCoreInfo.h>
  21. #include <AmdStyxAcpiLib.h>
  22. #include <Protocol/AmdMpCoreInfo.h>
  23. AMD_MP_CORE_INFO_PROTOCOL *mAmdMpCoreInfoProtocol = NULL;
  24. // ARM PL390 General Interrupt Controller
  25. #define GIC_BASE (FixedPcdGet64 (PcdGicInterruptInterfaceBase))
  26. #define GICD_BASE (FixedPcdGet64 (PcdGicDistributorBase))
  27. #define GICV_BASE (FixedPcdGet64 (PcdGicVirtualInterruptInterfaceBase))
  28. #define GICH_BASE (FixedPcdGet64 (PcdGicHypervisorInterruptInterfaceBase))
  29. #define VGIC_MAINT_INT (FixedPcdGet32 (PcdGicVirtualMaintenanceInterrupt))
  30. #define GICVR_BASE (FixedPcdGet64 (PcdGicVirtualRegisterInterfaceBase))
  31. #define GIC_MSI_FRAME (FixedPcdGet64 (PcdGicMSIFrameBase))
  32. #define GIC_VERSION (FixedPcdGet8 (PcdGicVersion))
  33. #define GICD_ID ( 0 )
  34. #define GICD_VECTOR ( 0 )
  35. #define GICM_ID ( 0 )
  36. #define GICM_SPI_COUNT ( 0x100 )
  37. #define GICM_SPI_BASE ( 0x40 )
  38. #define GSIV_SPI_OFFSET ( 32 )
  39. #if STYX_A0
  40. #define MSI_TYPER_FLAG ( 1 ) // Ignore TYPER register and use Count/Base fields
  41. #else
  42. #define MSI_TYPER_FLAG ( 0 ) // Use TYPER register and ignore Count/Base fields
  43. #endif
  44. #define PARKING_PROTOCOL_VERSION (FixedPcdGet32 (PcdParkingProtocolVersion))
  45. #define PARKED_OFFSET ( 4096 )
  46. #define CORES_PER_CLUSTER (FixedPcdGet32 (PcdSocCoresPerCluster))
  47. #define PARKED_ADDRESS(Base, ClusterId, CoreId) \
  48. ((Base) + (CORES_PER_CLUSTER * ClusterId + CoreId) * PARKED_OFFSET)
  49. /* Macro to populate EFI_ACPI_5_1_GIC_STRUCTURE */
  50. #define AMD_GIC(CpuNum, ClusterId, CoreId, PerfInt) { \
  51. EFI_ACPI_5_1_GIC, /* UINT8 Type */ \
  52. sizeof (EFI_ACPI_5_1_GIC_STRUCTURE), /* UINT8 Length */ \
  53. EFI_ACPI_RESERVED_WORD, /* UINT16 Reserved */ \
  54. CpuNum, /* UINT32 CPUInterfaceNumber */ \
  55. (ClusterId << 8) | CoreId, /* UINT32 AcpiProcessorUid */ \
  56. EFI_ACPI_5_1_GIC_ENABLED, /* UINT32 Flags */ \
  57. PARKING_PROTOCOL_VERSION, /* UINT32 ParkingProtocolVersion */ \
  58. PerfInt, /* UINT32 PerformanceInterruptGsiv */ \
  59. 0, /* UINT64 ParkedAddress */ \
  60. GIC_BASE, /* UINT64 PhysicalBaseAddress */ \
  61. GICV_BASE, /* UINT64 GICV */ \
  62. GICH_BASE, /* UINT64 GICH */ \
  63. VGIC_MAINT_INT, /* UINT32 VGICMaintenanceInterrupt */ \
  64. GICVR_BASE, /* UINT64 GICRBaseAddress */ \
  65. (ClusterId << 8) | CoreId /* UINT64 MPIDR */ \
  66. }
  67. /* Macro to initialise EFI_ACPI_5_1_GIC_DISTRIBUTOR_STRUCTURE */
  68. #define AMD_GICD(Id, Vec) { \
  69. EFI_ACPI_5_1_GICD, /* UINT8 Type */ \
  70. sizeof (EFI_ACPI_5_1_GIC_DISTRIBUTOR_STRUCTURE), /* UINT8 Length */ \
  71. EFI_ACPI_RESERVED_WORD, /* UINT16 Reserved1 */ \
  72. Id, /* UINT32 GicId */ \
  73. GICD_BASE, /* UINT64 PhysicalBaseAddress */ \
  74. Vec, /* UINT32 SystemVectorBase */ \
  75. EFI_ACPI_RESERVED_DWORD /* UINT32 Reserved2 */ \
  76. }
  77. /* Macro to initialise EFI_ACPI_5_1_GIC_MSI_FRAME_STRUCTURE */
  78. #define AMD_GICM(Id, SpiCount, SpiBase) { \
  79. EFI_ACPI_5_1_GIC_MSI_FRAME, /* UINT8 Type */ \
  80. sizeof(EFI_ACPI_5_1_GIC_MSI_FRAME_STRUCTURE), /* UINT8 Length */ \
  81. EFI_ACPI_RESERVED_WORD, /* UINT16 Reserved1 */ \
  82. Id, /* UINT32 GicMsiFrameId */ \
  83. GIC_MSI_FRAME, /* UINT64 PhysicalBaseAddress */ \
  84. MSI_TYPER_FLAG, /* UINT32 Flags */ \
  85. SpiCount, /* UINT16 SPICount */ \
  86. SpiBase /* UINT16 SPIBase */ \
  87. }
  88. //
  89. // NOTE: NUM_CORES is a pre-processor macro passed in with -D option
  90. //
  91. #pragma pack(push, 1)
  92. typedef struct {
  93. EFI_ACPI_5_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER Header;
  94. EFI_ACPI_5_1_GIC_STRUCTURE GicC[NUM_CORES];
  95. EFI_ACPI_5_1_GIC_DISTRIBUTOR_STRUCTURE GicD;
  96. EFI_ACPI_5_1_GIC_MSI_FRAME_STRUCTURE GicM;
  97. } EFI_ACPI_5_1_ARM_MADT_STRUCTURE;
  98. #pragma pack(pop)
  99. STATIC EFI_ACPI_5_1_ARM_MADT_STRUCTURE AcpiMadt = {
  100. {
  101. AMD_ACPI_HEADER (EFI_ACPI_5_1_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
  102. EFI_ACPI_5_1_ARM_MADT_STRUCTURE,
  103. EFI_ACPI_5_1_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION),
  104. GIC_BASE, // UINT32 LocalApicAddress
  105. 0 // UINT32 Flags
  106. },
  107. {
  108. /*
  109. * GIC Interface for Cluster 0 CPU 0
  110. */
  111. AMD_GIC(0, 0, 0, 39), // EFI_ACPI_5_1_GIC_STRUCTURE
  112. #if (NUM_CORES > 1)
  113. /*
  114. * GIC Interface for Cluster 0 CPU 1
  115. */
  116. AMD_GIC(1, 0, 1, 40), // EFI_ACPI_5_1_GIC_STRUCTURE
  117. #endif
  118. #if (NUM_CORES > 2)
  119. /*
  120. * GIC Interface for Cluster 1 CPU 0
  121. */
  122. AMD_GIC(2, 1, 0, 41), // EFI_ACPI_5_1_GIC_STRUCTURE
  123. #endif
  124. #if (NUM_CORES > 3)
  125. /*
  126. * GIC Interface for Cluster 1 CPU 1
  127. */
  128. AMD_GIC(3, 1, 1, 42), // EFI_ACPI_5_1_GIC_STRUCTURE
  129. #endif
  130. #if (NUM_CORES > 4)
  131. /*
  132. * GIC Interface for Cluster 2 CPU 0
  133. */
  134. AMD_GIC(4, 2, 0, 43), // EFI_ACPI_5_1_GIC_STRUCTURE
  135. #endif
  136. #if (NUM_CORES > 5)
  137. /*
  138. * GIC Interface for Cluster 2 CPU 1
  139. */
  140. AMD_GIC(5, 2, 1, 44), // EFI_ACPI_5_1_GIC_STRUCTURE
  141. #endif
  142. #if (NUM_CORES > 6)
  143. /*
  144. * GIC Interface for Cluster 3 CPU 0
  145. */
  146. AMD_GIC(6, 3, 0, 45), // EFI_ACPI_5_1_GIC_STRUCTURE
  147. #endif
  148. #if (NUM_CORES > 7)
  149. /*
  150. * GIC Interface for Cluster 3 CPU 1
  151. */
  152. AMD_GIC(7, 3, 1, 46), // EFI_ACPI_5_1_GIC_STRUCTURE
  153. #endif
  154. },
  155. /*
  156. * GIC Distributor
  157. */
  158. AMD_GICD(GICD_ID, GICD_VECTOR), // EFI_ACPI_5_1_GIC_DISTRIBUTOR_STRUCTURE
  159. /*
  160. * GIC MSI Frame
  161. */
  162. AMD_GICM(GICM_ID, GICM_SPI_COUNT, GICM_SPI_BASE),
  163. };
  164. STATIC
  165. EFI_STATUS
  166. BuildGicC (
  167. EFI_ACPI_5_1_GIC_STRUCTURE *GicC,
  168. UINT32 CpuNum,
  169. UINT32 ClusterId,
  170. UINT32 CoreId,
  171. EFI_PHYSICAL_ADDRESS MpParkingBase
  172. )
  173. {
  174. UINT32 MpId, PmuSpi;
  175. EFI_STATUS Status;
  176. MpId = (UINT32) GET_MPID (ClusterId, CoreId);
  177. Status = mAmdMpCoreInfoProtocol->GetPmuSpiFromMpId (MpId, &PmuSpi);
  178. if (EFI_ERROR (Status))
  179. return Status;
  180. GicC->Type = EFI_ACPI_5_1_GIC;
  181. GicC->Length = sizeof (EFI_ACPI_5_1_GIC_STRUCTURE);
  182. GicC->Reserved = EFI_ACPI_RESERVED_WORD;
  183. GicC->CPUInterfaceNumber = CpuNum;
  184. GicC->AcpiProcessorUid = MpId;
  185. GicC->Flags = EFI_ACPI_5_1_GIC_ENABLED;
  186. GicC->ParkingProtocolVersion = PARKING_PROTOCOL_VERSION;
  187. GicC->ParkedAddress = PARKED_ADDRESS(MpParkingBase, ClusterId, CoreId);
  188. GicC->PhysicalBaseAddress = GIC_BASE;
  189. GicC->GICV = GICV_BASE;
  190. GicC->GICH = GICH_BASE;
  191. GicC->VGICMaintenanceInterrupt = VGIC_MAINT_INT;
  192. GicC->GICRBaseAddress = GICVR_BASE;
  193. GicC->PerformanceInterruptGsiv = PmuSpi + GSIV_SPI_OFFSET;
  194. GicC->MPIDR = MpId;
  195. return EFI_SUCCESS;
  196. }
  197. STATIC
  198. VOID
  199. BuildGicD (
  200. EFI_ACPI_5_1_GIC_DISTRIBUTOR_STRUCTURE *GicD,
  201. UINT32 GicId,
  202. UINT32 SystemVectorBase
  203. )
  204. {
  205. GicD->Type = EFI_ACPI_5_1_GICD;
  206. GicD->Length = sizeof (EFI_ACPI_5_1_GIC_DISTRIBUTOR_STRUCTURE);
  207. GicD->Reserved1 = EFI_ACPI_RESERVED_WORD;
  208. GicD->GicId = GicId;
  209. GicD->PhysicalBaseAddress = GICD_BASE;
  210. GicD->SystemVectorBase = SystemVectorBase;
  211. #if 0
  212. GicD->Reserved2 = EFI_ACPI_RESERVED_DWORD;
  213. #else
  214. GicD->GicVersion = EFI_ACPI_RESERVED_BYTE;
  215. GicD->Reserved2[0] = EFI_ACPI_RESERVED_BYTE;
  216. GicD->Reserved2[1] = EFI_ACPI_RESERVED_BYTE;
  217. GicD->Reserved2[2] = EFI_ACPI_RESERVED_BYTE;
  218. #endif
  219. }
  220. STATIC
  221. VOID
  222. BuildGicM (
  223. EFI_ACPI_5_1_GIC_MSI_FRAME_STRUCTURE *GicM,
  224. UINT32 MsiFrameId,
  225. UINT16 SpiCount,
  226. UINT16 SpiBase
  227. )
  228. {
  229. GicM->Type = EFI_ACPI_5_1_GIC_MSI_FRAME;
  230. GicM->Length = sizeof(EFI_ACPI_5_1_GIC_MSI_FRAME_STRUCTURE);
  231. GicM->Reserved1 = EFI_ACPI_RESERVED_WORD;
  232. GicM->GicMsiFrameId = MsiFrameId;
  233. GicM->PhysicalBaseAddress = GIC_MSI_FRAME;
  234. GicM->Flags = MSI_TYPER_FLAG;
  235. GicM->SPICount = SpiCount;
  236. GicM->SPIBase = SpiBase;
  237. }
  238. EFI_ACPI_DESCRIPTION_HEADER *
  239. MadtHeader (
  240. VOID
  241. )
  242. {
  243. EFI_ACPI_5_1_GIC_STRUCTURE *GicC;
  244. EFI_ACPI_5_1_GIC_DISTRIBUTOR_STRUCTURE *GicD;
  245. EFI_ACPI_5_1_GIC_MSI_FRAME_STRUCTURE *GicM;
  246. ARM_CORE_INFO *ArmCoreInfoTable;
  247. UINTN CoreCount, CpuNum;
  248. EFI_STATUS Status;
  249. EFI_PHYSICAL_ADDRESS MpParkingBase;
  250. UINTN MpParkingSize;
  251. Status = gBS->LocateProtocol (
  252. &gAmdMpCoreInfoProtocolGuid,
  253. NULL,
  254. (VOID **)&mAmdMpCoreInfoProtocol
  255. );
  256. ASSERT_EFI_ERROR (Status);
  257. // Get pointer to ARM core info table
  258. ArmCoreInfoTable = mAmdMpCoreInfoProtocol->GetArmCoreInfoTable (&CoreCount);
  259. ASSERT (ArmCoreInfoTable != NULL);
  260. // Make sure SoC's core count does not exceed what we want to build
  261. ASSERT (CoreCount <= NUM_CORES);
  262. ASSERT (CoreCount <= PcdGet32(PcdSocCoreCount));
  263. MpParkingSize = 0;
  264. MpParkingBase = mAmdMpCoreInfoProtocol->GetMpParkingBase(&MpParkingSize);
  265. if (MpParkingBase && MpParkingSize < (CoreCount * SIZE_4KB)) {
  266. DEBUG ((EFI_D_ERROR, "MADT: Parking Protocol not supported.\n"));
  267. MpParkingBase = 0;
  268. }
  269. GicC = (EFI_ACPI_5_1_GIC_STRUCTURE *)&AcpiMadt.GicC[0];
  270. AcpiMadt.Header.Header.Length = sizeof (EFI_ACPI_5_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER);
  271. for (CpuNum = 0; CpuNum < CoreCount; ++CpuNum, ++GicC) {
  272. DEBUG ((EFI_D_ERROR, "MADT: Core[%d]: ClusterId = %d CoreId = %d\n",
  273. CpuNum, ArmCoreInfoTable[CpuNum].ClusterId, ArmCoreInfoTable[CpuNum].CoreId));
  274. Status = BuildGicC (GicC, CpuNum,
  275. ArmCoreInfoTable[CpuNum].ClusterId,
  276. ArmCoreInfoTable[CpuNum].CoreId,
  277. MpParkingBase
  278. );
  279. ASSERT_EFI_ERROR (Status);
  280. AcpiMadt.Header.Header.Length += sizeof (EFI_ACPI_5_1_GIC_STRUCTURE);
  281. }
  282. GicD = (EFI_ACPI_5_1_GIC_DISTRIBUTOR_STRUCTURE *)(UINT8 *)((UINTN)&AcpiMadt + (UINTN)AcpiMadt.Header.Header.Length);
  283. BuildGicD (GicD, GICD_ID, GICD_VECTOR);
  284. AcpiMadt.Header.Header.Length += sizeof (EFI_ACPI_5_1_GIC_DISTRIBUTOR_STRUCTURE);
  285. GicM = (EFI_ACPI_5_1_GIC_MSI_FRAME_STRUCTURE *)(UINT8 *)((UINTN)&AcpiMadt + (UINTN)AcpiMadt.Header.Header.Length);
  286. BuildGicM (GicM, GICM_ID, GICM_SPI_COUNT, GICM_SPI_BASE);
  287. AcpiMadt.Header.Header.Length += sizeof (EFI_ACPI_5_1_GIC_MSI_FRAME_STRUCTURE);
  288. return &AcpiMadt.Header.Header;
  289. }