4 Copyright (c) 2020, Arm Limited.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
8 - ACPI 6.3 Specification - January 2019
11 - MPDA - Memory Proximity Domain Attributes
12 - SLLBI - System Locality Latency and Bandwidth Information
13 - MSCI - Memory Side Cache Information
17 #include <Library/PrintLib.h>
18 #include <Library/BaseLib.h>
19 #include <Library/UefiLib.h>
20 #include "AcpiParser.h"
23 // Maximum Memory Domain matrix print size.
24 #define MAX_MEMORY_DOMAIN_TARGET_PRINT_MATRIX 10
27 STATIC CONST UINT16
* HmatStructureType
;
28 STATIC CONST UINT32
* HmatStructureLength
;
30 STATIC CONST UINT32
* NumberInitiatorProximityDomain
;
31 STATIC CONST UINT32
* NumberTargetProximityDomain
;
33 EFI_ACPI_6_3_HMAT_STRUCTURE_SYSTEM_LOCALITY_LATENCY_AND_BANDWIDTH_INFO_FLAGS
*
36 STATIC CONST UINT8
* SllbiDataType
;
37 STATIC CONST UINT16
* NumberSMBIOSHandles
;
39 STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo
;
42 Names of System Locality Latency Bandwidth Information (SLLBI) data types
44 STATIC CONST CHAR16
* SllbiNames
[] = {
45 L
"Access %sLatency%s",
48 L
"Access %sBandwidth%s",
49 L
"Read %sBandwidth%s",
50 L
"Write %sBandwidth%s"
54 This function validates the Cache Attributes field.
56 @param [in] Ptr Pointer to the start of the field data.
57 @param [in] Context Pointer to context specific information e.g. this
58 could be a pointer to the ACPI table header.
63 ValidateCacheAttributes (
68 EFI_ACPI_6_3_HMAT_STRUCTURE_MEMORY_SIDE_CACHE_INFO_CACHE_ATTRIBUTES
*
72 (EFI_ACPI_6_3_HMAT_STRUCTURE_MEMORY_SIDE_CACHE_INFO_CACHE_ATTRIBUTES
*)Ptr
;
74 if (Attributes
->TotalCacheLevels
> 0x3) {
75 IncrementErrorCount ();
77 L
"\nERROR: Attributes bits [3:0] have invalid value: 0x%x",
78 Attributes
->TotalCacheLevels
81 if (Attributes
->CacheLevel
> 0x3) {
82 IncrementErrorCount ();
84 L
"\nERROR: Attributes bits [7:4] have invalid value: 0x%x",
85 Attributes
->CacheLevel
88 if (Attributes
->CacheAssociativity
> 0x2) {
89 IncrementErrorCount ();
91 L
"\nERROR: Attributes bits [11:8] have invalid value: 0x%x",
92 Attributes
->CacheAssociativity
95 if (Attributes
->WritePolicy
> 0x2) {
96 IncrementErrorCount ();
98 L
"\nERROR: Attributes bits [15:12] have invalid value: 0x%x",
99 Attributes
->WritePolicy
105 Dumps the cache attributes field
107 @param [in] Format Optional format string for tracing the data.
108 @param [in] Ptr Pointer to the start of the buffer.
113 DumpCacheAttributes (
114 IN CONST CHAR16
* Format OPTIONAL
,
118 EFI_ACPI_6_3_HMAT_STRUCTURE_MEMORY_SIDE_CACHE_INFO_CACHE_ATTRIBUTES
*
122 (EFI_ACPI_6_3_HMAT_STRUCTURE_MEMORY_SIDE_CACHE_INFO_CACHE_ATTRIBUTES
*)Ptr
;
125 PrintFieldName (4, L
"Total Cache Levels");
126 Print (L
"%d\n", Attributes
->TotalCacheLevels
);
127 PrintFieldName (4, L
"Cache Level");
128 Print (L
"%d\n", Attributes
->CacheLevel
);
129 PrintFieldName (4, L
"Cache Associativity");
130 Print (L
"%d\n", Attributes
->CacheAssociativity
);
131 PrintFieldName (4, L
"Write Policy");
132 Print (L
"%d\n", Attributes
->WritePolicy
);
133 PrintFieldName (4, L
"Cache Line Size");
134 Print (L
"%d\n", Attributes
->CacheLineSize
);
138 An ACPI_PARSER array describing the ACPI HMAT Table.
140 STATIC CONST ACPI_PARSER HmatParser
[] = {
141 PARSE_ACPI_HEADER (&AcpiHdrInfo
),
142 {L
"Reserved", 4, 36, NULL
, NULL
, NULL
, NULL
, NULL
}
146 An ACPI_PARSER array describing the HMAT structure header.
148 STATIC CONST ACPI_PARSER HmatStructureHeaderParser
[] = {
149 {L
"Type", 2, 0, NULL
, NULL
, (VOID
**)&HmatStructureType
, NULL
, NULL
},
150 {L
"Reserved", 2, 2, NULL
, NULL
, NULL
, NULL
, NULL
},
151 {L
"Length", 4, 4, NULL
, NULL
, (VOID
**)&HmatStructureLength
, NULL
, NULL
}
155 An ACPI PARSER array describing the Memory Proximity Domain Attributes
158 STATIC CONST ACPI_PARSER MemProximityDomainAttributeParser
[] = {
159 {L
"Type", 2, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
160 {L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
161 {L
"Length", 4, 4, L
"%d", NULL
, NULL
, NULL
, NULL
},
162 {L
"Flags", 2, 8, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
163 {L
"Reserved", 2, 10, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
164 {L
"Proximity Dom for initiator", 4, 12, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
165 {L
"Proximity Dom for memory", 4, 16, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
166 {L
"Reserved", 4, 20, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
167 {L
"Reserved", 8, 24, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
168 {L
"Reserved", 8, 32, L
"0x%lx", NULL
, NULL
, NULL
, NULL
}
172 An ACPI PARSER array describing the System Locality Latency and Bandwidth
173 Information Structure - Type 1.
175 STATIC CONST ACPI_PARSER SllbiParser
[] = {
176 {L
"Type", 2, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
177 {L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
178 {L
"Length", 4, 4, L
"%d", NULL
, NULL
, NULL
, NULL
},
179 {L
"Flags", 1, 8, L
"0x%x", NULL
, (VOID
**)&SllbiFlags
, NULL
, NULL
},
180 {L
"Data type", 1, 9, L
"0x%x", NULL
, (VOID
**)&SllbiDataType
, NULL
, NULL
},
181 {L
"Reserved", 2, 10, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
182 {L
"Initiator Proximity Dom Count", 4, 12, L
"%d", NULL
,
183 (VOID
**)&NumberInitiatorProximityDomain
, NULL
, NULL
},
184 {L
"Target Proximity Dom Count", 4, 16, L
"%d", NULL
,
185 (VOID
**)&NumberTargetProximityDomain
, NULL
, NULL
},
186 {L
"Reserved", 4, 20, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
187 {L
"Entry Base Unit", 8, 24, L
"0x%lx", NULL
, NULL
, NULL
, NULL
}
188 // initiator Proximity Domain list ...
189 // target Proximity Domain list ...
190 // Latency/Bandwidth matrix ...
194 An ACPI PARSER array describing the Memory Side Cache Information
197 STATIC CONST ACPI_PARSER MemSideCacheInfoParser
[] = {
198 {L
"Type", 2, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
199 {L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
200 {L
"Length", 4, 4, L
"%d", NULL
, NULL
, NULL
, NULL
},
201 {L
"Proximity Dom for memory", 4, 8, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
202 {L
"Reserved", 4, 12, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
203 {L
"Memory Side Cache Size", 8, 16, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
204 {L
"Cache Attributes", 4, 24, NULL
, DumpCacheAttributes
, NULL
,
205 ValidateCacheAttributes
, NULL
},
206 {L
"Reserved", 2, 28, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
207 {L
"SMBIOS Handle Count", 2, 30, L
"%d", NULL
,
208 (VOID
**)&NumberSMBIOSHandles
, NULL
, NULL
}
209 // SMBIOS handles List ...
213 This function parses the Memory Proximity Domain Attributes
216 @param [in] Ptr Pointer to the start of the Memory Proximity Domain
217 Attributes Structure data.
218 @param [in] Length Length of the Memory Proximity Domain Attributes
231 "Memory Proximity Domain Attributes Structure",
234 PARSER_PARAMS (MemProximityDomainAttributeParser
)
239 This function parses the System Locality Latency and Bandwidth Information
242 @param [in] Ptr Pointer to the start of the System Locality Latency and
243 Bandwidth Information Structure data.
244 @param [in] Length Length of the System Locality Latency and Bandwidth
245 Information Structure.
254 CONST UINT32
* InitiatorProximityDomainList
;
255 CONST UINT32
* TargetProximityDomainList
;
256 CONST UINT16
* LatencyBandwidthMatrix
;
258 CHAR16 Buffer
[OUTPUT_FIELD_COLUMN_WIDTH
];
259 CHAR16 SecondBuffer
[OUTPUT_FIELD_COLUMN_WIDTH
];
260 UINT32 RequiredTableSize
;
262 UINT32 IndexInitiator
;
264 UINT32 TargetStartOffset
;
269 "System Locality Latency and Bandwidth Information Structure",
272 PARSER_PARAMS (SllbiParser
)
275 // Check if the values used to control the parsing logic have been
276 // successfully read.
277 if ((SllbiFlags
== NULL
) ||
278 (SllbiDataType
== NULL
) ||
279 (NumberInitiatorProximityDomain
== NULL
) ||
280 (NumberTargetProximityDomain
== NULL
)) {
281 IncrementErrorCount ();
283 L
"ERROR: Insufficient remaining table buffer length to read the " \
284 L
"SLLBI structure header. Length = %d.\n",
290 RequiredTableSize
= (*NumberInitiatorProximityDomain
* sizeof (UINT32
)) +
291 (*NumberTargetProximityDomain
* sizeof (UINT32
)) +
292 (*NumberInitiatorProximityDomain
*
293 *NumberTargetProximityDomain
* sizeof (UINT16
)) +
296 if (RequiredTableSize
> Length
) {
297 IncrementErrorCount ();
299 L
"ERROR: Insufficient System Locality Latency and Bandwidth" \
300 L
"Information Structure length. TableLength = %d. " \
301 L
"RequiredTableLength = %d.\n",
308 InitiatorProximityDomainList
= (UINT32
*) (Ptr
+ Offset
);
309 TargetProximityDomainList
= InitiatorProximityDomainList
+
310 *NumberInitiatorProximityDomain
;
311 LatencyBandwidthMatrix
= (UINT16
*) (TargetProximityDomainList
+
312 *NumberTargetProximityDomain
);
314 // Display each element of the Initiator Proximity Domain list
315 for (Index
= 0; Index
< *NumberInitiatorProximityDomain
; Index
++) {
319 L
"Initiator Proximity Dom [%d]",
323 PrintFieldName (4, Buffer
);
326 InitiatorProximityDomainList
[Index
]
330 // Display each element of the Target Proximity Domain list
331 for (Index
= 0; Index
< *NumberTargetProximityDomain
; Index
++) {
335 L
"Target Proximity Dom [%d]",
339 PrintFieldName (4, Buffer
);
342 TargetProximityDomainList
[Index
]
346 // Create base name depending on Data Type in this Structure
347 if (*SllbiDataType
>= ARRAY_SIZE (SllbiNames
)) {
348 IncrementErrorCount ();
349 Print (L
"Error: Unkown Data Type. DataType = 0x%x.\n", *SllbiDataType
);
352 StrCpyS (Buffer
, sizeof (Buffer
), SllbiNames
[*SllbiDataType
]);
354 // Adjust base name depending on Memory Hierarchy in this Structure
355 switch (SllbiFlags
->MemoryHierarchy
) {
359 sizeof (SecondBuffer
),
370 sizeof (SecondBuffer
),
377 IncrementErrorCount ();
379 L
"Error: Invalid Memory Hierarchy. MemoryHierarchy = %d.\n",
380 SllbiFlags
->MemoryHierarchy
386 if (*NumberTargetProximityDomain
<= MAX_MEMORY_DOMAIN_TARGET_PRINT_MATRIX
) {
387 // Display the latency/bandwidth matrix as a matrix
394 PrintFieldName (4, Buffer
);
396 Print (L
"\n Target : X-axis (Horizontal)");
397 Print (L
"\n Initiator : Y-axis (Vertical)");
400 for (IndexTarget
= 0;
401 IndexTarget
< *NumberTargetProximityDomain
;
403 Print (L
" %2d", IndexTarget
);
407 for (IndexTarget
= 0;
408 IndexTarget
< *NumberTargetProximityDomain
;
414 TargetStartOffset
= 0;
415 for (IndexInitiator
= 0;
416 IndexInitiator
< *NumberInitiatorProximityDomain
;
418 Print (L
" %2d |", IndexInitiator
);
419 for (IndexTarget
= 0;
420 IndexTarget
< *NumberTargetProximityDomain
;
424 LatencyBandwidthMatrix
[TargetStartOffset
+ IndexTarget
]
428 TargetStartOffset
+= (*NumberTargetProximityDomain
);
432 // Display the latency/bandwidth matrix as a list
440 TargetStartOffset
= 0;
441 for (IndexInitiator
= 0;
442 IndexInitiator
< *NumberInitiatorProximityDomain
;
444 for (IndexTarget
= 0;
445 IndexTarget
< *NumberTargetProximityDomain
;
449 sizeof (SecondBuffer
),
455 PrintFieldName (4, SecondBuffer
);
458 LatencyBandwidthMatrix
[TargetStartOffset
+ IndexTarget
]
461 TargetStartOffset
+= (*NumberTargetProximityDomain
);
467 This function parses the Memory Side Cache Information Structure (Type 2).
469 @param [in] Ptr Pointer to the start of the Memory Side Cache Information
471 @param [in] Length Length of the Memory Side Cache Information Structure.
480 CONST UINT16
* SMBIOSHandlesList
;
481 CHAR16 Buffer
[OUTPUT_FIELD_COLUMN_WIDTH
];
488 "Memory Side Cache Information Structure",
491 PARSER_PARAMS (MemSideCacheInfoParser
)
494 // Check if the values used to control the parsing logic have been
495 // successfully read.
496 if (NumberSMBIOSHandles
== NULL
) {
497 IncrementErrorCount ();
499 L
"ERROR: Insufficient remaining table buffer length to read the " \
500 L
"MSCI structure header. Length = %d.\n",
506 if ((*NumberSMBIOSHandles
* sizeof (UINT16
)) > (Length
- Offset
)) {
507 IncrementErrorCount ();
509 L
"ERROR: Invalid Number of SMBIOS Handles. SMBIOSHandlesCount = %d." \
510 L
"RemainingBufferLength = %d.\n",
511 *NumberSMBIOSHandles
,
517 SMBIOSHandlesList
= (UINT16
*) (Ptr
+ Offset
);
519 for (Index
= 0; Index
< *NumberSMBIOSHandles
; Index
++) {
523 L
"SMBIOS Handles [%d]",
527 PrintFieldName (4, Buffer
);
530 SMBIOSHandlesList
[Index
]
536 This function parses the ACPI HMAT table.
537 When trace is enabled this function parses the HMAT table and
538 traces the ACPI table fields.
540 This function parses the following HMAT structures:
541 - Memory Proximity Domain Attributes Structure (Type 0)
542 - System Locality Latency and Bandwidth Info Structure (Type 1)
543 - Memory Side Cache Info structure (Type 2)
545 This function also performs validation of the ACPI table fields.
547 @param [in] Trace If TRUE, trace the ACPI fields.
548 @param [in] Ptr Pointer to the start of the buffer.
549 @param [in] AcpiTableLength Length of the ACPI table.
550 @param [in] AcpiTableRevision Revision of the ACPI table.
557 IN UINT32 AcpiTableLength
,
558 IN UINT8 AcpiTableRevision
562 UINT8
* HmatStructurePtr
;
574 PARSER_PARAMS (HmatParser
)
577 HmatStructurePtr
= Ptr
+ Offset
;
579 while (Offset
< AcpiTableLength
) {
580 // Parse HMAT Structure Header to obtain Type and Length.
586 AcpiTableLength
- Offset
,
587 PARSER_PARAMS (HmatStructureHeaderParser
)
590 // Check if the values used to control the parsing logic have been
591 // successfully read.
592 if ((HmatStructureType
== NULL
) ||
593 (HmatStructureLength
== NULL
)) {
594 IncrementErrorCount ();
596 L
"ERROR: Insufficient remaining table buffer length to read the " \
597 L
"HMAT structure header. Length = %d.\n",
598 AcpiTableLength
- Offset
603 // Validate HMAT Structure length.
604 if ((*HmatStructureLength
== 0) ||
605 ((Offset
+ (*HmatStructureLength
)) > AcpiTableLength
)) {
606 IncrementErrorCount ();
608 L
"ERROR: Invalid HMAT Structure length. " \
609 L
"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
610 *HmatStructureLength
,
617 switch (*HmatStructureType
) {
618 case EFI_ACPI_6_3_HMAT_TYPE_MEMORY_PROXIMITY_DOMAIN_ATTRIBUTES
:
624 case EFI_ACPI_6_3_HMAT_TYPE_SYSTEM_LOCALITY_LATENCY_AND_BANDWIDTH_INFO
:
630 case EFI_ACPI_6_3_HMAT_TYPE_MEMORY_SIDE_CACHE_INFO
:
637 IncrementErrorCount ();
639 L
"ERROR: Unknown HMAT structure:"
640 L
" Type = %d, Length = %d\n",
647 HmatStructurePtr
+= *HmatStructureLength
;
648 Offset
+= *HmatStructureLength
;