4 Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
5 Copyright (c) 2022, AMD Incorporated. All rights reserved.
6 SPDX-License-Identifier: BSD-2-Clause-Patent
9 - ACPI 6.3 Specification - January 2019
10 - Arm Generic Interrupt Controller Architecture Specification,
11 GIC architecture version 3 and version 4, issue E
12 - Arm Server Base System Architecture 5.0
15 #include <IndustryStandard/Acpi.h>
16 #include <Library/UefiLib.h>
17 #include "AcpiParser.h"
18 #include "AcpiTableParser.h"
19 #include "AcpiViewConfig.h"
20 #include "MadtParser.h"
23 STATIC CONST UINT8
*MadtInterruptControllerType
;
24 STATIC CONST UINT8
*MadtInterruptControllerLength
;
25 STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo
;
28 This function validates the System Vector Base in the GICD.
30 @param [in] Ptr Pointer to the start of the field data.
31 @param [in] Context Pointer to context specific information e.g. this
32 could be a pointer to the ACPI table header.
37 ValidateGICDSystemVectorBase (
42 if (*(UINT32
*)Ptr
!= 0) {
43 IncrementErrorCount ();
45 L
"\nERROR: System Vector Base must be zero."
51 This function validates the SPE Overflow Interrupt in the GICC.
53 @param [in] Ptr Pointer to the start of the field data.
54 @param [in] Context Pointer to context specific information e.g. this
55 could be a pointer to the ACPI table header.
60 ValidateSpeOverflowInterrupt (
65 UINT16 SpeOverflowInterrupt
;
67 SpeOverflowInterrupt
= *(UINT16
*)Ptr
;
69 // SPE not supported by this processor
70 if (SpeOverflowInterrupt
== 0) {
74 if ((SpeOverflowInterrupt
< ARM_PPI_ID_MIN
) ||
75 ((SpeOverflowInterrupt
> ARM_PPI_ID_MAX
) &&
76 (SpeOverflowInterrupt
< ARM_PPI_ID_EXTENDED_MIN
)) ||
77 (SpeOverflowInterrupt
> ARM_PPI_ID_EXTENDED_MAX
))
79 IncrementErrorCount ();
81 L
"\nERROR: SPE Overflow Interrupt ID of %d is not in the allowed PPI ID "
82 L
"ranges of %d-%d or %d-%d (for GICv3.1 or later).",
86 ARM_PPI_ID_EXTENDED_MIN
,
87 ARM_PPI_ID_EXTENDED_MAX
89 } else if (SpeOverflowInterrupt
!= ARM_PPI_ID_PMBIRQ
) {
90 IncrementWarningCount ();
92 L
"\nWARNING: SPE Overflow Interrupt ID of %d is not compliant with SBSA "
93 L
"Level 3 PPI ID assignment: %d.",
101 An ACPI_PARSER array describing the GICC Interrupt Controller Structure.
103 STATIC CONST ACPI_PARSER GicCParser
[] = {
104 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
105 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
106 { L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
108 { L
"CPU Interface Number", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
109 { L
"ACPI Processor UID", 4, 8, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
110 { L
"Flags", 4, 12, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
111 { L
"Parking Protocol Version", 4, 16, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
113 { L
"Performance Interrupt GSIV", 4, 20, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
114 { L
"Parked Address", 8, 24, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
115 { L
"Physical Base Address", 8, 32, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
116 { L
"GICV", 8, 40, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
117 { L
"GICH", 8, 48, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
118 { L
"VGIC Maintenance interrupt", 4, 56, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
119 { L
"GICR Base Address", 8, 60, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
120 { L
"MPIDR", 8, 68, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
121 { L
"Processor Power Efficiency Class", 1, 76, L
"0x%x", NULL
, NULL
, NULL
,
123 { L
"Reserved", 1, 77, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
124 { L
"SPE overflow Interrupt", 2, 78, L
"0x%x", NULL
, NULL
,
125 ValidateSpeOverflowInterrupt
, NULL
}
129 An ACPI_PARSER array describing the GICD Interrupt Controller Structure.
131 STATIC CONST ACPI_PARSER GicDParser
[] = {
132 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
133 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
134 { L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
136 { L
"GIC ID", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
137 { L
"Physical Base Address", 8, 8, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
138 { L
"System Vector Base", 4, 16, L
"0x%x", NULL
, NULL
,
139 ValidateGICDSystemVectorBase
, NULL
},
140 { L
"GIC Version", 1, 20, L
"%d", NULL
, NULL
, NULL
, NULL
},
141 { L
"Reserved", 3, 21, L
"%x %x %x", Dump3Chars
, NULL
, NULL
, NULL
}
145 An ACPI_PARSER array describing the MSI Frame Interrupt Controller Structure.
147 STATIC CONST ACPI_PARSER GicMSIFrameParser
[] = {
148 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
149 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
150 { L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
152 { L
"MSI Frame ID", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
153 { L
"Physical Base Address", 8, 8, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
154 { L
"Flags", 4, 16, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
156 { L
"SPI Count", 2, 20, L
"%d", NULL
, NULL
, NULL
, NULL
},
157 { L
"SPI Base", 2, 22, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
161 An ACPI_PARSER array describing the GICR Interrupt Controller Structure.
163 STATIC CONST ACPI_PARSER GicRParser
[] = {
164 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
165 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
166 { L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
168 { L
"Discovery Range Base Address", 8, 4, L
"0x%lx", NULL
, NULL
, NULL
,
170 { L
"Discovery Range Length", 4, 12, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
174 An ACPI_PARSER array describing the GIC ITS Interrupt Controller Structure.
176 STATIC CONST ACPI_PARSER GicITSParser
[] = {
177 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
178 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
179 { L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
181 { L
"GIC ITS ID", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
182 { L
"Physical Base Address", 8, 8, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
183 { L
"Reserved", 4, 16, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
187 An ACPI_PARSER array describing the IO APIC Structure.
189 STATIC CONST ACPI_PARSER IoApic
[] = {
190 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
191 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
192 { L
"I/O APIC ID", 1, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
193 { L
"Reserved", 1, 3, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
194 { L
"I/O APIC Address", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
195 { L
"Global System Interrupt Base", 4, 8, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
199 An ACPI_PARSER array describing the Interrupt Source Override Structure.
201 STATIC CONST ACPI_PARSER InterruptSourceOverride
[] = {
202 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
203 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
204 { L
"Bus", 1, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
205 { L
"Source", 1, 3, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
206 { L
"Global System Interrupt", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
207 { L
"Flags", 2, 8, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
210 STATIC CONST ACPI_PARSER LocalApicFlags
[] = {
211 { L
"Enabled", 1, 0, L
"%d", NULL
, NULL
, NULL
, NULL
},
212 { L
"Online Capable", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
213 { L
"Reserved", 30, 2, L
"%d", NULL
, NULL
, NULL
, NULL
}
217 This function traces Bit Flags fields.
218 If no format string is specified the Format must be NULL.
220 @param [in] Format Optional format string for tracing the data.
221 @param [in] Ptr Pointer to the start of the buffer.
225 DumpLocalApicBitFlags (
226 IN CONST CHAR16
*Format OPTIONAL
,
230 if (Format
!= NULL
) {
231 Print (Format
, *(UINT32
*)Ptr
);
235 Print (L
"0x%X\n", *(UINT32
*)Ptr
);
242 PARSER_PARAMS (LocalApicFlags
)
247 An ACPI_PARSER array describing the Processor Local APIC Structure.
249 STATIC CONST ACPI_PARSER ProcessorLocalApic
[] = {
250 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
251 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
253 { L
"ACPI Processor UID", 1, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
254 { L
"APIC ID", 1, 3, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
255 { L
"Flags", 4, 4, NULL
, DumpLocalApicBitFlags
, NULL
, NULL
, NULL
}
259 An ACPI_PARSER array describing the Processor Local x2APIC Structure.
261 STATIC CONST ACPI_PARSER ProcessorLocalX2Apic
[] = {
262 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
263 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
264 { L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
266 { L
"X2APIC ID", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
267 { L
"Flags", 4, 8, NULL
, DumpLocalApicBitFlags
, NULL
, NULL
, NULL
},
268 { L
"ACPI Processor UID", 4, 12, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
272 An ACPI_PARSER array describing the Local x2APIC NMI Structure.
274 STATIC CONST ACPI_PARSER LocalX2ApicNmi
[] = {
275 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
276 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
277 { L
"Flags", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
279 { L
"ACPI Processor UID", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
280 { L
"Local x2APIC LINT#", 1, 8, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
281 { L
"Reserved", 3, 9, L
"0x%x%x%x", Dump3Chars
, NULL
, NULL
, NULL
}
285 An ACPI_PARSER array describing the ACPI MADT Table.
287 STATIC CONST ACPI_PARSER MadtParser
[] = {
288 PARSE_ACPI_HEADER (&AcpiHdrInfo
),
289 { L
"Local Interrupt Controller Address",4, 36, L
"0x%x", NULL
, NULL
, NULL
,
291 { L
"Flags", 4, 40, L
"0x%x", NULL
, NULL
, NULL
,NULL
}
295 An ACPI_PARSER array describing the MADT Interrupt Controller Structure Header Structure.
297 STATIC CONST ACPI_PARSER MadtInterruptControllerHeaderParser
[] = {
298 { NULL
, 1, 0, NULL
, NULL
, (VOID
**)&MadtInterruptControllerType
, NULL
, NULL
},
299 { L
"Length", 1, 1, NULL
, NULL
, (VOID
**)&MadtInterruptControllerLength
, NULL
,
301 { L
"Reserved", 2, 2, NULL
, NULL
, NULL
, NULL
, NULL
}
305 This function parses the ACPI MADT table.
306 When trace is enabled this function parses the MADT table and
307 traces the ACPI table fields.
309 This function currently parses the following Interrupt Controller
317 This function also performs validation of the ACPI table fields.
319 @param [in] Trace If TRUE, trace the ACPI fields.
320 @param [in] Ptr Pointer to the start of the buffer.
321 @param [in] AcpiTableLength Length of the ACPI table.
322 @param [in] AcpiTableRevision Revision of the ACPI table.
329 IN UINT32 AcpiTableLength
,
330 IN UINT8 AcpiTableRevision
334 UINT8
*InterruptContollerPtr
;
349 PARSER_PARAMS (MadtParser
)
351 InterruptContollerPtr
= Ptr
+ Offset
;
353 while (Offset
< AcpiTableLength
) {
354 // Parse Interrupt Controller Structure to obtain Length.
359 InterruptContollerPtr
,
360 AcpiTableLength
- Offset
,
361 PARSER_PARAMS (MadtInterruptControllerHeaderParser
)
364 // Check if the values used to control the parsing logic have been
365 // successfully read.
366 if ((MadtInterruptControllerType
== NULL
) ||
367 (MadtInterruptControllerLength
== NULL
))
369 IncrementErrorCount ();
371 L
"ERROR: Insufficient remaining table buffer length to read the " \
372 L
"Interrupt Controller Structure header. Length = %d.\n",
373 AcpiTableLength
- Offset
378 // Validate Interrupt Controller Structure length
379 if ((*MadtInterruptControllerLength
== 0) ||
380 ((Offset
+ (*MadtInterruptControllerLength
)) > AcpiTableLength
))
382 IncrementErrorCount ();
384 L
"ERROR: Invalid Interrupt Controller Structure length. " \
385 L
"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
386 *MadtInterruptControllerLength
,
393 switch (*MadtInterruptControllerType
) {
394 case EFI_ACPI_6_3_GIC
:
400 InterruptContollerPtr
,
401 *MadtInterruptControllerLength
,
402 PARSER_PARAMS (GicCParser
)
407 case EFI_ACPI_6_3_GICD
:
409 if (++GICDCount
> 1) {
410 IncrementErrorCount ();
412 L
"ERROR: Only one GICD must be present,"
413 L
" GICDCount = %d\n",
422 InterruptContollerPtr
,
423 *MadtInterruptControllerLength
,
424 PARSER_PARAMS (GicDParser
)
429 case EFI_ACPI_6_3_GIC_MSI_FRAME
:
435 InterruptContollerPtr
,
436 *MadtInterruptControllerLength
,
437 PARSER_PARAMS (GicMSIFrameParser
)
442 case EFI_ACPI_6_3_GICR
:
448 InterruptContollerPtr
,
449 *MadtInterruptControllerLength
,
450 PARSER_PARAMS (GicRParser
)
455 case EFI_ACPI_6_3_GIC_ITS
:
461 InterruptContollerPtr
,
462 *MadtInterruptControllerLength
,
463 PARSER_PARAMS (GicITSParser
)
468 case EFI_ACPI_6_3_IO_APIC
:
474 InterruptContollerPtr
,
475 *MadtInterruptControllerLength
,
476 PARSER_PARAMS (IoApic
)
481 case EFI_ACPI_6_3_INTERRUPT_SOURCE_OVERRIDE
:
486 "INTERRUPT SOURCE OVERRIDE",
487 InterruptContollerPtr
,
488 *MadtInterruptControllerLength
,
489 PARSER_PARAMS (InterruptSourceOverride
)
493 case EFI_ACPI_6_3_PROCESSOR_LOCAL_APIC
:
498 "PROCESSOR LOCAL APIC",
499 InterruptContollerPtr
,
500 *MadtInterruptControllerLength
,
501 PARSER_PARAMS (ProcessorLocalApic
)
505 case EFI_ACPI_6_3_PROCESSOR_LOCAL_X2APIC
:
510 "PROCESSOR LOCAL X2APIC",
511 InterruptContollerPtr
,
512 *MadtInterruptControllerLength
,
513 PARSER_PARAMS (ProcessorLocalX2Apic
)
518 case EFI_ACPI_6_3_LOCAL_X2APIC_NMI
:
524 InterruptContollerPtr
,
525 *MadtInterruptControllerLength
,
526 PARSER_PARAMS (LocalX2ApicNmi
)
533 IncrementErrorCount ();
535 L
"ERROR: Unknown Interrupt Controller Structure,"
536 L
" Type = %d, Length = %d\n",
537 *MadtInterruptControllerType
,
538 *MadtInterruptControllerLength
543 InterruptContollerPtr
+= *MadtInterruptControllerLength
;
544 Offset
+= *MadtInterruptControllerLength
;