4 Copyright (c) 2019 - 2021, ARM Limited. All rights reserved.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
8 - ACPI 6.4 Specification - January 2021
9 - ARM Architecture Reference Manual ARMv8 (D.a)
12 #include <Library/PrintLib.h>
13 #include <Library/UefiLib.h>
14 #include "AcpiParser.h"
16 #include "AcpiViewConfig.h"
17 #include "PpttParser.h"
20 STATIC CONST UINT8
*ProcessorTopologyStructureType
;
21 STATIC CONST UINT8
*ProcessorTopologyStructureLength
;
22 STATIC CONST UINT32
*NumberOfPrivateResources
;
23 STATIC CONST EFI_ACPI_6_4_PPTT_STRUCTURE_CACHE_FLAGS
*CacheFlags
;
24 STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo
;
26 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
29 Increment the error count and print an error that a required flag is missing.
31 @param [in] FlagName Name of the missing flag.
37 IN CONST CHAR16
*FlagName
40 IncrementErrorCount ();
42 L
"\nERROR: On Arm based systems, all cache properties must be"
43 L
" provided in the cache type structure."
44 L
" Missing '%s' flag.",
52 This function validates the Cache Type Structure (Type 1) Cache Flags field.
54 @param [in] Ptr Pointer to the start of the field data.
55 @param [in] Context Pointer to context specific information e.g. this
56 could be a pointer to the ACPI table header.
66 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
67 CacheFlags
= (EFI_ACPI_6_4_PPTT_STRUCTURE_CACHE_FLAGS
*)Ptr
;
69 if (CacheFlags
== NULL
) {
70 IncrementErrorCount ();
71 Print (L
"\nERROR: Cache Structure Flags were not successfully read.");
75 if (CacheFlags
->SizePropertyValid
== EFI_ACPI_6_4_PPTT_CACHE_SIZE_INVALID
) {
76 LogCacheFlagError (L
"Size Property Valid");
79 if (CacheFlags
->NumberOfSetsValid
== EFI_ACPI_6_4_PPTT_NUMBER_OF_SETS_INVALID
) {
80 LogCacheFlagError (L
"Number Of Sets Valid");
83 if (CacheFlags
->AssociativityValid
== EFI_ACPI_6_4_PPTT_ASSOCIATIVITY_INVALID
) {
84 LogCacheFlagError (L
"Associativity Valid");
87 if (CacheFlags
->AllocationTypeValid
== EFI_ACPI_6_4_PPTT_ALLOCATION_TYPE_INVALID
) {
88 LogCacheFlagError (L
"Allocation Type Valid");
91 if (CacheFlags
->CacheTypeValid
== EFI_ACPI_6_4_PPTT_CACHE_TYPE_INVALID
) {
92 LogCacheFlagError (L
"Cache Type Valid");
95 if (CacheFlags
->WritePolicyValid
== EFI_ACPI_6_4_PPTT_WRITE_POLICY_INVALID
) {
96 LogCacheFlagError (L
"Write Policy Valid");
99 if (CacheFlags
->LineSizeValid
== EFI_ACPI_6_4_PPTT_LINE_SIZE_INVALID
) {
100 LogCacheFlagError (L
"Line Size Valid");
103 // Cache ID was only introduced in revision 3
104 if (*(AcpiHdrInfo
.Revision
) >= 3) {
105 if (CacheFlags
->CacheIdValid
== EFI_ACPI_6_4_PPTT_CACHE_ID_INVALID
) {
106 LogCacheFlagError (L
"Cache Id Valid");
114 This function validates the Cache Type Structure (Type 1) 'Number of sets'
117 @param [in] Ptr Pointer to the start of the field data.
118 @param [in] Context Pointer to context specific information e.g. this
119 could be a pointer to the ACPI table header.
124 ValidateCacheNumberOfSets (
131 NumberOfSets
= *(UINT32
*)Ptr
;
133 if (NumberOfSets
== 0) {
134 IncrementErrorCount ();
135 Print (L
"\nERROR: Cache number of sets must be greater than 0");
139 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
140 if (NumberOfSets
> PPTT_ARM_CCIDX_CACHE_NUMBER_OF_SETS_MAX
) {
141 IncrementErrorCount ();
143 L
"\nERROR: When ARMv8.3-CCIDX is implemented the maximum cache number of "
144 L
"sets must be less than or equal to %d",
145 PPTT_ARM_CCIDX_CACHE_NUMBER_OF_SETS_MAX
150 if (NumberOfSets
> PPTT_ARM_CACHE_NUMBER_OF_SETS_MAX
) {
151 IncrementWarningCount ();
153 L
"\nWARNING: Without ARMv8.3-CCIDX, the maximum cache number of sets "
154 L
"must be less than or equal to %d. Ignore this message if "
155 L
"ARMv8.3-CCIDX is implemented",
156 PPTT_ARM_CACHE_NUMBER_OF_SETS_MAX
165 This function validates the Cache Type Structure (Type 1) 'Associativity'
168 @param [in] Ptr Pointer to the start of the field data.
169 @param [in] Context Pointer to context specific information e.g. this
170 could be a pointer to the ACPI table header.
175 ValidateCacheAssociativity (
182 Associativity
= *(UINT8
*)Ptr
;
184 if (Associativity
== 0) {
185 IncrementErrorCount ();
186 Print (L
"\nERROR: Cache associativity must be greater than 0");
192 This function validates the Cache Type Structure (Type 1) Line size field.
194 @param [in] Ptr Pointer to the start of the field data.
195 @param [in] Context Pointer to context specific information e.g. this
196 could be a pointer to the ACPI table header.
201 ValidateCacheLineSize (
206 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
207 // Reference: ARM Architecture Reference Manual ARMv8 (D.a)
208 // Section D12.2.25: CCSIDR_EL1, Current Cache Size ID Register
209 // LineSize, bits [2:0]
210 // (Log2(Number of bytes in cache line)) - 4.
213 LineSize
= *(UINT16
*)Ptr
;
215 if ((LineSize
< PPTT_ARM_CACHE_LINE_SIZE_MIN
) ||
216 (LineSize
> PPTT_ARM_CACHE_LINE_SIZE_MAX
))
218 IncrementErrorCount ();
220 L
"\nERROR: The cache line size must be between %d and %d bytes"
221 L
" on ARM Platforms.",
222 PPTT_ARM_CACHE_LINE_SIZE_MIN
,
223 PPTT_ARM_CACHE_LINE_SIZE_MAX
228 if ((LineSize
& (LineSize
- 1)) != 0) {
229 IncrementErrorCount ();
230 Print (L
"\nERROR: The cache line size is not a power of 2.");
237 This function validates the Cache Type Structure (Type 1) Cache ID field.
239 @param [in] Ptr Pointer to the start of the field data.
240 @param [in] Context Pointer to context specific information e.g. this
241 could be a pointer to the ACPI table header.
253 CacheId
= *(UINT32
*)Ptr
;
255 // Cache ID was only introduced in revision 3
256 if (*(AcpiHdrInfo
.Revision
) < 3) {
260 if (CacheFlags
== NULL
) {
261 IncrementErrorCount ();
262 Print (L
"\nERROR: Cache Structure Flags were not successfully read.");
266 if (CacheFlags
->CacheIdValid
== EFI_ACPI_6_4_PPTT_CACHE_ID_VALID
) {
268 IncrementErrorCount ();
269 Print (L
"\nERROR: 0 is not a valid Cache ID.");
276 This function validates the Cache Type Structure (Type 1) Attributes field.
278 @param [in] Ptr Pointer to the start of the field data.
279 @param [in] Context Pointer to context specific information e.g. this
280 could be a pointer to the ACPI table header.
285 ValidateCacheAttributes (
290 // Reference: Advanced Configuration and Power Interface (ACPI) Specification
291 // Version 6.4, January 2021
292 // Table 5-140: Cache Type Structure
295 Attributes
= *(UINT8
*)Ptr
;
297 if ((Attributes
& 0xE0) != 0) {
298 IncrementErrorCount ();
300 L
"\nERROR: Attributes bits [7:5] are reserved and must be zero.",
308 An ACPI_PARSER array describing the ACPI PPTT Table.
310 STATIC CONST ACPI_PARSER PpttParser
[] = {
311 PARSE_ACPI_HEADER (&AcpiHdrInfo
)
315 An ACPI_PARSER array describing the processor topology structure header.
317 STATIC CONST ACPI_PARSER ProcessorTopologyStructureHeaderParser
[] = {
318 { L
"Type", 1, 0, NULL
, NULL
, (VOID
**)&ProcessorTopologyStructureType
,
320 { L
"Length", 1, 1, NULL
, NULL
, (VOID
**)&ProcessorTopologyStructureLength
,
322 { L
"Reserved", 2, 2, NULL
, NULL
, NULL
, NULL
,NULL
}
326 An ACPI_PARSER array describing the Processor Hierarchy Node Structure - Type 0.
328 STATIC CONST ACPI_PARSER ProcessorHierarchyNodeStructureParser
[] = {
329 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
330 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
331 { L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
333 { L
"Flags", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
334 { L
"Parent", 4, 8, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
335 { L
"ACPI Processor ID", 4, 12, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
336 { L
"Number of private resources", 4, 16, L
"%d", NULL
,
337 (VOID
**)&NumberOfPrivateResources
, NULL
, NULL
}
341 An ACPI_PARSER array describing the Cache Type Structure - Type 1.
343 STATIC CONST ACPI_PARSER CacheTypeStructureParser
[] = {
344 { L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
345 { L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
346 { L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
348 { L
"Flags", 4, 4, L
"0x%x", NULL
, (VOID
**)&CacheFlags
, ValidateCacheFlags
,
350 { L
"Next Level of Cache", 4, 8, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
351 { L
"Size", 4, 12, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
352 { L
"Number of sets", 4, 16, L
"%d", NULL
, NULL
, ValidateCacheNumberOfSets
, NULL
},
353 { L
"Associativity", 1, 20, L
"%d", NULL
, NULL
, ValidateCacheAssociativity
, NULL
},
354 { L
"Attributes", 1, 21, L
"0x%x", NULL
, NULL
, ValidateCacheAttributes
, NULL
},
355 { L
"Line size", 2, 22, L
"%d", NULL
, NULL
, ValidateCacheLineSize
, NULL
},
356 { L
"Cache ID", 4, 24, L
"%d", NULL
, NULL
, ValidateCacheId
, NULL
}
360 This function parses the Processor Hierarchy Node Structure (Type 0).
362 @param [in] Ptr Pointer to the start of the Processor Hierarchy Node
364 @param [in] Length Length of the Processor Hierarchy Node Structure.
368 DumpProcessorHierarchyNodeStructure (
375 CHAR16 Buffer
[OUTPUT_FIELD_COLUMN_WIDTH
];
380 "Processor Hierarchy Node Structure",
383 PARSER_PARAMS (ProcessorHierarchyNodeStructureParser
)
386 // Check if the values used to control the parsing logic have been
387 // successfully read.
388 if (NumberOfPrivateResources
== NULL
) {
389 IncrementErrorCount ();
391 L
"ERROR: Insufficient Processor Hierarchy Node length. Length = %d.\n",
397 // Make sure the Private Resource array lies inside this structure
398 if (Offset
+ (*NumberOfPrivateResources
* sizeof (UINT32
)) > Length
) {
399 IncrementErrorCount ();
401 L
"ERROR: Invalid Number of Private Resources. " \
402 L
"PrivateResourceCount = %d. RemainingBufferLength = %d. " \
403 L
"Parsing of this structure aborted.\n",
404 *NumberOfPrivateResources
,
412 // Parse the specified number of private resource references or the Processor
413 // Hierarchy Node length. Whichever is minimum.
414 while (Index
< *NumberOfPrivateResources
) {
418 L
"Private resources [%d]",
422 PrintFieldName (4, Buffer
);
425 *((UINT32
*)(Ptr
+ Offset
))
428 Offset
+= sizeof (UINT32
);
434 This function parses the Cache Type Structure (Type 1).
436 @param [in] Ptr Pointer to the start of the Cache Type Structure data.
437 @param [in] Length Length of the Cache Type Structure.
441 DumpCacheTypeStructure (
449 "Cache Type Structure",
452 PARSER_PARAMS (CacheTypeStructureParser
)
457 This function parses the ACPI PPTT table.
458 When trace is enabled this function parses the PPTT table and
459 traces the ACPI table fields.
461 This function parses the following processor topology structures:
462 - Processor hierarchy node structure (Type 0)
463 - Cache Type Structure (Type 1)
465 This function also performs validation of the ACPI table fields.
467 @param [in] Trace If TRUE, trace the ACPI fields.
468 @param [in] Ptr Pointer to the start of the buffer.
469 @param [in] AcpiTableLength Length of the ACPI table.
470 @param [in] AcpiTableRevision Revision of the ACPI table.
477 IN UINT32 AcpiTableLength
,
478 IN UINT8 AcpiTableRevision
482 UINT8
*ProcessorTopologyStructurePtr
;
494 PARSER_PARAMS (PpttParser
)
497 ProcessorTopologyStructurePtr
= Ptr
+ Offset
;
499 while (Offset
< AcpiTableLength
) {
500 // Parse Processor Hierarchy Node Structure to obtain Type and Length.
505 ProcessorTopologyStructurePtr
,
506 AcpiTableLength
- Offset
,
507 PARSER_PARAMS (ProcessorTopologyStructureHeaderParser
)
510 // Check if the values used to control the parsing logic have been
511 // successfully read.
512 if ((ProcessorTopologyStructureType
== NULL
) ||
513 (ProcessorTopologyStructureLength
== NULL
))
515 IncrementErrorCount ();
517 L
"ERROR: Insufficient remaining table buffer length to read the " \
518 L
"processor topology structure header. Length = %d.\n",
519 AcpiTableLength
- Offset
524 // Validate Processor Topology Structure length
525 if ((*ProcessorTopologyStructureLength
== 0) ||
526 ((Offset
+ (*ProcessorTopologyStructureLength
)) > AcpiTableLength
))
528 IncrementErrorCount ();
530 L
"ERROR: Invalid Processor Topology Structure length. " \
531 L
"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
532 *ProcessorTopologyStructureLength
,
539 PrintFieldName (2, L
"* Structure Offset *");
540 Print (L
"0x%x\n", Offset
);
542 switch (*ProcessorTopologyStructureType
) {
543 case EFI_ACPI_6_4_PPTT_TYPE_PROCESSOR
:
544 DumpProcessorHierarchyNodeStructure (
545 ProcessorTopologyStructurePtr
,
546 *ProcessorTopologyStructureLength
549 case EFI_ACPI_6_4_PPTT_TYPE_CACHE
:
550 DumpCacheTypeStructure (
551 ProcessorTopologyStructurePtr
,
552 *ProcessorTopologyStructureLength
555 case EFI_ACPI_6_3_PPTT_TYPE_ID
:
556 IncrementErrorCount ();
558 L
"ERROR: PPTT Type 2 - Processor ID has been removed and must not be"
563 IncrementErrorCount ();
565 L
"ERROR: Unknown processor topology structure:"
566 L
" Type = %d, Length = %d\n",
567 *ProcessorTopologyStructureType
,
568 *ProcessorTopologyStructureLength
572 ProcessorTopologyStructurePtr
+= *ProcessorTopologyStructureLength
;
573 Offset
+= *ProcessorTopologyStructureLength
;