4 Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
8 - ACPI 6.3 Specification - January 2019
9 - Arm Generic Interrupt Controller Architecture Specification,
10 GIC architecture version 3 and version 4, issue E
11 - Arm Server Base System Architecture 5.0
14 #include <IndustryStandard/Acpi.h>
15 #include <Library/UefiLib.h>
16 #include "AcpiParser.h"
17 #include "AcpiTableParser.h"
18 #include "AcpiViewConfig.h"
19 #include "MadtParser.h"
22 STATIC CONST UINT8
*MadtInterruptControllerType
;
23 STATIC CONST UINT8
*MadtInterruptControllerLength
;
24 STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo
;
27 This function validates the System Vector Base in the GICD.
29 @param [in] Ptr Pointer to the start of the field data.
30 @param [in] Context Pointer to context specific information e.g. this
31 could be a pointer to the ACPI table header.
36 ValidateGICDSystemVectorBase (
41 if (*(UINT32
*)Ptr
!= 0) {
42 IncrementErrorCount ();
44 L
"\nERROR: System Vector Base must be zero."
50 This function validates the SPE Overflow Interrupt in the GICC.
52 @param [in] Ptr Pointer to the start of the field data.
53 @param [in] Context Pointer to context specific information e.g. this
54 could be a pointer to the ACPI table header.
59 ValidateSpeOverflowInterrupt (
64 UINT16 SpeOverflowInterrupt
;
66 SpeOverflowInterrupt
= *(UINT16
*)Ptr
;
68 // SPE not supported by this processor
69 if (SpeOverflowInterrupt
== 0) {
73 if ((SpeOverflowInterrupt
< ARM_PPI_ID_MIN
) ||
74 ((SpeOverflowInterrupt
> ARM_PPI_ID_MAX
) &&
75 (SpeOverflowInterrupt
< ARM_PPI_ID_EXTENDED_MIN
)) ||
76 (SpeOverflowInterrupt
> ARM_PPI_ID_EXTENDED_MAX
))
78 IncrementErrorCount ();
80 L
"\nERROR: SPE Overflow Interrupt ID of %d is not in the allowed PPI ID "
81 L
"ranges of %d-%d or %d-%d (for GICv3.1 or later).",
85 ARM_PPI_ID_EXTENDED_MIN
,
86 ARM_PPI_ID_EXTENDED_MAX
88 } else if (SpeOverflowInterrupt
!= ARM_PPI_ID_PMBIRQ
) {
89 IncrementWarningCount ();
91 L
"\nWARNING: SPE Overflow Interrupt ID of %d is not compliant with SBSA "
92 L
"Level 3 PPI ID assignment: %d.",
100 An ACPI_PARSER array describing the GICC Interrupt Controller Structure.
102 STATIC CONST ACPI_PARSER GicCParser
[] = {
103 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
104 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
105 { L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
107 { L
"CPU Interface Number", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
108 { L
"ACPI Processor UID", 4, 8, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
109 { L
"Flags", 4, 12, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
110 { L
"Parking Protocol Version", 4, 16, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
112 { L
"Performance Interrupt GSIV", 4, 20, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
113 { L
"Parked Address", 8, 24, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
114 { L
"Physical Base Address", 8, 32, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
115 { L
"GICV", 8, 40, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
116 { L
"GICH", 8, 48, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
117 { L
"VGIC Maintenance interrupt", 4, 56, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
118 { L
"GICR Base Address", 8, 60, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
119 { L
"MPIDR", 8, 68, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
120 { L
"Processor Power Efficiency Class", 1, 76, L
"0x%x", NULL
, NULL
, NULL
,
122 { L
"Reserved", 1, 77, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
123 { L
"SPE overflow Interrupt", 2, 78, L
"0x%x", NULL
, NULL
,
124 ValidateSpeOverflowInterrupt
, NULL
}
128 An ACPI_PARSER array describing the GICD Interrupt Controller Structure.
130 STATIC CONST ACPI_PARSER GicDParser
[] = {
131 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
132 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
133 { L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
135 { L
"GIC ID", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
136 { L
"Physical Base Address", 8, 8, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
137 { L
"System Vector Base", 4, 16, L
"0x%x", NULL
, NULL
,
138 ValidateGICDSystemVectorBase
, NULL
},
139 { L
"GIC Version", 1, 20, L
"%d", NULL
, NULL
, NULL
, NULL
},
140 { L
"Reserved", 3, 21, L
"%x %x %x", Dump3Chars
, NULL
, NULL
, NULL
}
144 An ACPI_PARSER array describing the MSI Frame Interrupt Controller Structure.
146 STATIC CONST ACPI_PARSER GicMSIFrameParser
[] = {
147 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
148 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
149 { L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
151 { L
"MSI Frame ID", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
152 { L
"Physical Base Address", 8, 8, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
153 { L
"Flags", 4, 16, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
155 { L
"SPI Count", 2, 20, L
"%d", NULL
, NULL
, NULL
, NULL
},
156 { L
"SPI Base", 2, 22, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
160 An ACPI_PARSER array describing the GICR Interrupt Controller Structure.
162 STATIC CONST ACPI_PARSER GicRParser
[] = {
163 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
164 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
165 { L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
167 { L
"Discovery Range Base Address", 8, 4, L
"0x%lx", NULL
, NULL
, NULL
,
169 { L
"Discovery Range Length", 4, 12, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
173 An ACPI_PARSER array describing the GIC ITS Interrupt Controller Structure.
175 STATIC CONST ACPI_PARSER GicITSParser
[] = {
176 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
177 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
178 { L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
180 { L
"GIC ITS ID", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
181 { L
"Physical Base Address", 8, 8, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
182 { L
"Reserved", 4, 16, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
186 An ACPI_PARSER array describing the IO APIC Structure.
188 STATIC CONST ACPI_PARSER IoApic
[] = {
189 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
190 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
191 { L
"I/O APIC ID", 1, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
192 { L
"Reserved", 1, 3, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
193 { L
"I/O APIC Address", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
194 { L
"Global System Interrupt Base", 4, 8, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
198 An ACPI_PARSER array describing the Interrupt Source Override Structure.
200 STATIC CONST ACPI_PARSER InterruptSourceOverride
[] = {
201 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
202 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
203 { L
"Bus", 1, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
204 { L
"Source", 1, 3, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
205 { L
"Global System Interrupt", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
206 { L
"Flags", 2, 8, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
210 An ACPI_PARSER array describing the Processor Local x2APIC Structure.
212 STATIC CONST ACPI_PARSER ProcessorLocalX2Apic
[] = {
213 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
214 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
215 { L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
217 { L
"X2APIC ID", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
218 { L
"Flags", 4, 8, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
219 { L
"ACPI Processor UID", 4, 12, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
223 An ACPI_PARSER array describing the Local x2APIC NMI Structure.
225 STATIC CONST ACPI_PARSER LocalX2ApicNmi
[] = {
226 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
227 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
228 { L
"Flags", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
230 { L
"ACPI Processor UID", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
231 { L
"Local x2APIC LINT#", 1, 8, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
232 { L
"Reserved", 3, 9, L
"0x%x%x%x", Dump3Chars
, NULL
, NULL
, NULL
}
236 An ACPI_PARSER array describing the ACPI MADT Table.
238 STATIC CONST ACPI_PARSER MadtParser
[] = {
239 PARSE_ACPI_HEADER (&AcpiHdrInfo
),
240 { L
"Local Interrupt Controller Address",4, 36, L
"0x%x", NULL
, NULL
, NULL
,
242 { L
"Flags", 4, 40, L
"0x%x", NULL
, NULL
, NULL
,NULL
}
246 An ACPI_PARSER array describing the MADT Interrupt Controller Structure Header Structure.
248 STATIC CONST ACPI_PARSER MadtInterruptControllerHeaderParser
[] = {
249 { NULL
, 1, 0, NULL
, NULL
, (VOID
**)&MadtInterruptControllerType
, NULL
, NULL
},
250 { L
"Length", 1, 1, NULL
, NULL
, (VOID
**)&MadtInterruptControllerLength
, NULL
,
252 { L
"Reserved", 2, 2, NULL
, NULL
, NULL
, NULL
, NULL
}
256 This function parses the ACPI MADT table.
257 When trace is enabled this function parses the MADT table and
258 traces the ACPI table fields.
260 This function currently parses the following Interrupt Controller
268 This function also performs validation of the ACPI table fields.
270 @param [in] Trace If TRUE, trace the ACPI fields.
271 @param [in] Ptr Pointer to the start of the buffer.
272 @param [in] AcpiTableLength Length of the ACPI table.
273 @param [in] AcpiTableRevision Revision of the ACPI table.
280 IN UINT32 AcpiTableLength
,
281 IN UINT8 AcpiTableRevision
285 UINT8
*InterruptContollerPtr
;
300 PARSER_PARAMS (MadtParser
)
302 InterruptContollerPtr
= Ptr
+ Offset
;
304 while (Offset
< AcpiTableLength
) {
305 // Parse Interrupt Controller Structure to obtain Length.
310 InterruptContollerPtr
,
311 AcpiTableLength
- Offset
,
312 PARSER_PARAMS (MadtInterruptControllerHeaderParser
)
315 // Check if the values used to control the parsing logic have been
316 // successfully read.
317 if ((MadtInterruptControllerType
== NULL
) ||
318 (MadtInterruptControllerLength
== NULL
))
320 IncrementErrorCount ();
322 L
"ERROR: Insufficient remaining table buffer length to read the " \
323 L
"Interrupt Controller Structure header. Length = %d.\n",
324 AcpiTableLength
- Offset
329 // Validate Interrupt Controller Structure length
330 if ((*MadtInterruptControllerLength
== 0) ||
331 ((Offset
+ (*MadtInterruptControllerLength
)) > AcpiTableLength
))
333 IncrementErrorCount ();
335 L
"ERROR: Invalid Interrupt Controller Structure length. " \
336 L
"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
337 *MadtInterruptControllerLength
,
344 switch (*MadtInterruptControllerType
) {
345 case EFI_ACPI_6_3_GIC
:
351 InterruptContollerPtr
,
352 *MadtInterruptControllerLength
,
353 PARSER_PARAMS (GicCParser
)
358 case EFI_ACPI_6_3_GICD
:
360 if (++GICDCount
> 1) {
361 IncrementErrorCount ();
363 L
"ERROR: Only one GICD must be present,"
364 L
" GICDCount = %d\n",
373 InterruptContollerPtr
,
374 *MadtInterruptControllerLength
,
375 PARSER_PARAMS (GicDParser
)
380 case EFI_ACPI_6_3_GIC_MSI_FRAME
:
386 InterruptContollerPtr
,
387 *MadtInterruptControllerLength
,
388 PARSER_PARAMS (GicMSIFrameParser
)
393 case EFI_ACPI_6_3_GICR
:
399 InterruptContollerPtr
,
400 *MadtInterruptControllerLength
,
401 PARSER_PARAMS (GicRParser
)
406 case EFI_ACPI_6_3_GIC_ITS
:
412 InterruptContollerPtr
,
413 *MadtInterruptControllerLength
,
414 PARSER_PARAMS (GicITSParser
)
419 case EFI_ACPI_6_3_IO_APIC
:
425 InterruptContollerPtr
,
426 *MadtInterruptControllerLength
,
427 PARSER_PARAMS (IoApic
)
432 case EFI_ACPI_6_3_INTERRUPT_SOURCE_OVERRIDE
:
437 "INTERRUPT SOURCE OVERRIDE",
438 InterruptContollerPtr
,
439 *MadtInterruptControllerLength
,
440 PARSER_PARAMS (InterruptSourceOverride
)
445 case EFI_ACPI_6_3_PROCESSOR_LOCAL_X2APIC
:
450 "PROCESSOR LOCAL X2APIC",
451 InterruptContollerPtr
,
452 *MadtInterruptControllerLength
,
453 PARSER_PARAMS (ProcessorLocalX2Apic
)
458 case EFI_ACPI_6_3_LOCAL_X2APIC_NMI
:
464 InterruptContollerPtr
,
465 *MadtInterruptControllerLength
,
466 PARSER_PARAMS (LocalX2ApicNmi
)
473 IncrementErrorCount ();
475 L
"ERROR: Unknown Interrupt Controller Structure,"
476 L
" Type = %d, Length = %d\n",
477 *MadtInterruptControllerType
,
478 *MadtInterruptControllerLength
483 InterruptContollerPtr
+= *MadtInterruptControllerLength
;
484 Offset
+= *MadtInterruptControllerLength
;