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