123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667 |
- /** @file
- HMAT table parser
- Copyright (c) 2020, Arm Limited.
- SPDX-License-Identifier: BSD-2-Clause-Patent
- @par Reference(s):
- - ACPI 6.3 Specification - January 2019
- @par Glossary:
- - MPDA - Memory Proximity Domain Attributes
- - SLLBI - System Locality Latency and Bandwidth Information
- - MSCI - Memory Side Cache Information
- - Dom - Domain
- **/
- #include <Library/PrintLib.h>
- #include <Library/BaseLib.h>
- #include <Library/UefiLib.h>
- #include "AcpiParser.h"
- #include "AcpiView.h"
- // Maximum Memory Domain matrix print size.
- #define MAX_MEMORY_DOMAIN_TARGET_PRINT_MATRIX 10
- // Local variables
- STATIC CONST UINT16 *HmatStructureType;
- STATIC CONST UINT32 *HmatStructureLength;
- STATIC CONST UINT32 *NumberInitiatorProximityDomain;
- STATIC CONST UINT32 *NumberTargetProximityDomain;
- STATIC CONST
- EFI_ACPI_6_4_HMAT_STRUCTURE_SYSTEM_LOCALITY_LATENCY_AND_BANDWIDTH_INFO_FLAGS *
- SllbiFlags;
- STATIC CONST UINT8 *SllbiDataType;
- STATIC CONST UINT16 *NumberSMBIOSHandles;
- STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
- /**
- Names of System Locality Latency Bandwidth Information (SLLBI) data types
- **/
- STATIC CONST CHAR16 *SllbiNames[] = {
- L"Access %sLatency%s",
- L"Read %sLatency%s",
- L"Write %sLatency%s",
- L"Access %sBandwidth%s",
- L"Read %sBandwidth%s",
- L"Write %sBandwidth%s"
- };
- /**
- This function validates the Cache Attributes field.
- @param [in] Ptr Pointer to the start of the field data.
- @param [in] Context Pointer to context specific information e.g. this
- could be a pointer to the ACPI table header.
- **/
- STATIC
- VOID
- EFIAPI
- ValidateCacheAttributes (
- IN UINT8 *Ptr,
- IN VOID *Context
- )
- {
- EFI_ACPI_6_4_HMAT_STRUCTURE_MEMORY_SIDE_CACHE_INFO_CACHE_ATTRIBUTES *
- Attributes;
- Attributes =
- (EFI_ACPI_6_4_HMAT_STRUCTURE_MEMORY_SIDE_CACHE_INFO_CACHE_ATTRIBUTES *)Ptr;
- if (Attributes->TotalCacheLevels > 0x3) {
- IncrementErrorCount ();
- Print (
- L"\nERROR: Attributes bits [3:0] have invalid value: 0x%x",
- Attributes->TotalCacheLevels
- );
- }
- if (Attributes->CacheLevel > 0x3) {
- IncrementErrorCount ();
- Print (
- L"\nERROR: Attributes bits [7:4] have invalid value: 0x%x",
- Attributes->CacheLevel
- );
- }
- if (Attributes->CacheAssociativity > 0x2) {
- IncrementErrorCount ();
- Print (
- L"\nERROR: Attributes bits [11:8] have invalid value: 0x%x",
- Attributes->CacheAssociativity
- );
- }
- if (Attributes->WritePolicy > 0x2) {
- IncrementErrorCount ();
- Print (
- L"\nERROR: Attributes bits [15:12] have invalid value: 0x%x",
- Attributes->WritePolicy
- );
- }
- }
- /**
- Dumps the cache attributes field
- @param [in] Format Optional format string for tracing the data.
- @param [in] Ptr Pointer to the start of the buffer.
- **/
- STATIC
- VOID
- EFIAPI
- DumpCacheAttributes (
- IN CONST CHAR16 *Format OPTIONAL,
- IN UINT8 *Ptr
- )
- {
- EFI_ACPI_6_4_HMAT_STRUCTURE_MEMORY_SIDE_CACHE_INFO_CACHE_ATTRIBUTES *
- Attributes;
- Attributes =
- (EFI_ACPI_6_4_HMAT_STRUCTURE_MEMORY_SIDE_CACHE_INFO_CACHE_ATTRIBUTES *)Ptr;
- Print (L"\n");
- PrintFieldName (4, L"Total Cache Levels");
- Print (L"%d\n", Attributes->TotalCacheLevels);
- PrintFieldName (4, L"Cache Level");
- Print (L"%d\n", Attributes->CacheLevel);
- PrintFieldName (4, L"Cache Associativity");
- Print (L"%d\n", Attributes->CacheAssociativity);
- PrintFieldName (4, L"Write Policy");
- Print (L"%d\n", Attributes->WritePolicy);
- PrintFieldName (4, L"Cache Line Size");
- Print (L"%d\n", Attributes->CacheLineSize);
- }
- /**
- An ACPI_PARSER array describing the ACPI HMAT Table.
- */
- STATIC CONST ACPI_PARSER HmatParser[] = {
- PARSE_ACPI_HEADER (&AcpiHdrInfo),
- { L"Reserved", 4,36, NULL, NULL, NULL, NULL, NULL }
- };
- /**
- An ACPI_PARSER array describing the HMAT structure header.
- */
- STATIC CONST ACPI_PARSER HmatStructureHeaderParser[] = {
- { L"Type", 2, 0, NULL, NULL, (VOID **)&HmatStructureType, NULL, NULL },
- { L"Reserved", 2, 2, NULL, NULL, NULL, NULL, NULL },
- { L"Length", 4, 4, NULL, NULL, (VOID **)&HmatStructureLength, NULL, NULL }
- };
- /**
- An ACPI PARSER array describing the Memory Proximity Domain Attributes
- Structure - Type 0.
- */
- STATIC CONST ACPI_PARSER MemProximityDomainAttributeParser[] = {
- { L"Type", 2, 0, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Length", 4, 4, L"%d", NULL, NULL, NULL, NULL },
- { L"Flags", 2, 8, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Reserved", 2, 10, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Proximity Dom for initiator", 4, 12, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Proximity Dom for memory", 4, 16, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Reserved", 4, 20, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Reserved", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL },
- { L"Reserved", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL }
- };
- /**
- An ACPI PARSER array describing the System Locality Latency and Bandwidth
- Information Structure - Type 1.
- */
- STATIC CONST ACPI_PARSER SllbiParser[] = {
- { L"Type", 2, 0, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Length", 4, 4, L"%d", NULL, NULL, NULL, NULL },
- { L"Flags", 1, 8, L"0x%x", NULL, (VOID **)&SllbiFlags, NULL, NULL },
- { L"Data type", 1, 9, L"0x%x", NULL, (VOID **)&SllbiDataType, NULL, NULL },
- { L"Min Transfer Size", 1, 10, L"%d", NULL, NULL, NULL, NULL },
- { L"Reserved", 1, 11, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Initiator Proximity Dom Count", 4, 12, L"%d", NULL,
- (VOID **)&NumberInitiatorProximityDomain, NULL, NULL },
- { L"Target Proximity Dom Count", 4, 16, L"%d", NULL,
- (VOID **)&NumberTargetProximityDomain, NULL, NULL },
- { L"Reserved", 4, 20, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Entry Base Unit", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL }
- // initiator Proximity Domain list ...
- // target Proximity Domain list ...
- // Latency/Bandwidth matrix ...
- };
- /**
- An ACPI PARSER array describing the Memory Side Cache Information
- Structure - Type 2.
- */
- STATIC CONST ACPI_PARSER MemSideCacheInfoParser[] = {
- { L"Type", 2, 0, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Length", 4, 4, L"%d", NULL, NULL, NULL, NULL },
- { L"Proximity Dom for memory", 4, 8, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Reserved", 4, 12, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Memory Side Cache Size", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL },
- { L"Cache Attributes", 4, 24, NULL, DumpCacheAttributes, NULL,
- ValidateCacheAttributes, NULL },
- { L"Reserved", 2, 28, L"0x%x", NULL, NULL, NULL, NULL },
- { L"SMBIOS Handle Count", 2, 30, L"%d", NULL,
- (VOID **)&NumberSMBIOSHandles, NULL, NULL }
- // SMBIOS handles List ...
- };
- /**
- This function parses the Memory Proximity Domain Attributes
- Structure (Type 0).
- @param [in] Ptr Pointer to the start of the Memory Proximity Domain
- Attributes Structure data.
- @param [in] Length Length of the Memory Proximity Domain Attributes
- Structure.
- **/
- STATIC
- VOID
- DumpMpda (
- IN UINT8 *Ptr,
- IN UINT32 Length
- )
- {
- ParseAcpi (
- TRUE,
- 2,
- "Memory Proximity Domain Attributes Structure",
- Ptr,
- Length,
- PARSER_PARAMS (MemProximityDomainAttributeParser)
- );
- }
- /**
- This function parses the System Locality Latency and Bandwidth Information
- Structure (Type 1).
- @param [in] Ptr Pointer to the start of the System Locality Latency and
- Bandwidth Information Structure data.
- @param [in] Length Length of the System Locality Latency and Bandwidth
- Information Structure.
- **/
- STATIC
- VOID
- DumpSllbi (
- IN UINT8 *Ptr,
- IN UINT32 Length
- )
- {
- CONST UINT32 *InitiatorProximityDomainList;
- CONST UINT32 *TargetProximityDomainList;
- CONST UINT16 *LatencyBandwidthMatrix;
- UINT32 Offset;
- CHAR16 Buffer[OUTPUT_FIELD_COLUMN_WIDTH];
- CHAR16 SecondBuffer[OUTPUT_FIELD_COLUMN_WIDTH];
- UINT32 RequiredTableSize;
- UINT32 Index;
- UINT32 IndexInitiator;
- UINT32 IndexTarget;
- UINT32 TargetStartOffset;
- Offset = ParseAcpi (
- TRUE,
- 2,
- "System Locality Latency and Bandwidth Information Structure",
- Ptr,
- Length,
- PARSER_PARAMS (SllbiParser)
- );
- // Check if the values used to control the parsing logic have been
- // successfully read.
- if ((SllbiFlags == NULL) ||
- (SllbiDataType == NULL) ||
- (NumberInitiatorProximityDomain == NULL) ||
- (NumberTargetProximityDomain == NULL))
- {
- IncrementErrorCount ();
- Print (
- L"ERROR: Insufficient remaining table buffer length to read the " \
- L"SLLBI structure header. Length = %d.\n",
- Length
- );
- return;
- }
- RequiredTableSize = (*NumberInitiatorProximityDomain * sizeof (UINT32)) +
- (*NumberTargetProximityDomain * sizeof (UINT32)) +
- (*NumberInitiatorProximityDomain *
- *NumberTargetProximityDomain * sizeof (UINT16)) +
- Offset;
- if (RequiredTableSize > Length) {
- IncrementErrorCount ();
- Print (
- L"ERROR: Insufficient System Locality Latency and Bandwidth" \
- L"Information Structure length. TableLength = %d. " \
- L"RequiredTableLength = %d.\n",
- Length,
- RequiredTableSize
- );
- return;
- }
- InitiatorProximityDomainList = (UINT32 *)(Ptr + Offset);
- TargetProximityDomainList = InitiatorProximityDomainList +
- *NumberInitiatorProximityDomain;
- LatencyBandwidthMatrix = (UINT16 *)(TargetProximityDomainList +
- *NumberTargetProximityDomain);
- // Display each element of the Initiator Proximity Domain list
- for (Index = 0; Index < *NumberInitiatorProximityDomain; Index++) {
- UnicodeSPrint (
- Buffer,
- sizeof (Buffer),
- L"Initiator Proximity Dom [%d]",
- Index
- );
- PrintFieldName (4, Buffer);
- Print (
- L"0x%x\n",
- InitiatorProximityDomainList[Index]
- );
- }
- // Display each element of the Target Proximity Domain list
- for (Index = 0; Index < *NumberTargetProximityDomain; Index++) {
- UnicodeSPrint (
- Buffer,
- sizeof (Buffer),
- L"Target Proximity Dom [%d]",
- Index
- );
- PrintFieldName (4, Buffer);
- Print (
- L"0x%x\n",
- TargetProximityDomainList[Index]
- );
- }
- // Create base name depending on Data Type in this Structure
- if (*SllbiDataType >= ARRAY_SIZE (SllbiNames)) {
- IncrementErrorCount ();
- Print (L"Error: Unkown Data Type. DataType = 0x%x.\n", *SllbiDataType);
- return;
- }
- StrCpyS (Buffer, sizeof (Buffer), SllbiNames[*SllbiDataType]);
- // Adjust base name depending on Memory Hierarchy in this Structure
- switch (SllbiFlags->MemoryHierarchy) {
- case 0:
- UnicodeSPrint (
- SecondBuffer,
- sizeof (SecondBuffer),
- Buffer,
- L"",
- L"%s"
- );
- break;
- case 1:
- case 2:
- case 3:
- UnicodeSPrint (
- SecondBuffer,
- sizeof (SecondBuffer),
- Buffer,
- L"Hit ",
- L"%s"
- );
- break;
- default:
- IncrementErrorCount ();
- Print (
- L"Error: Invalid Memory Hierarchy. MemoryHierarchy = %d.\n",
- SllbiFlags->MemoryHierarchy
- );
- return;
- } // switch
- if (*NumberTargetProximityDomain <= MAX_MEMORY_DOMAIN_TARGET_PRINT_MATRIX) {
- // Display the latency/bandwidth matrix as a matrix
- UnicodeSPrint (
- Buffer,
- sizeof (Buffer),
- SecondBuffer,
- L""
- );
- PrintFieldName (4, Buffer);
- Print (L"\n Target : X-axis (Horizontal)");
- Print (L"\n Initiator : Y-axis (Vertical)");
- Print (L"\n |");
- for (IndexTarget = 0;
- IndexTarget < *NumberTargetProximityDomain;
- IndexTarget++)
- {
- Print (L" %2d", IndexTarget);
- }
- Print (L"\n ---+");
- for (IndexTarget = 0;
- IndexTarget < *NumberTargetProximityDomain;
- IndexTarget++)
- {
- Print (L"------");
- }
- Print (L"\n");
- TargetStartOffset = 0;
- for (IndexInitiator = 0;
- IndexInitiator < *NumberInitiatorProximityDomain;
- IndexInitiator++)
- {
- Print (L" %2d |", IndexInitiator);
- for (IndexTarget = 0;
- IndexTarget < *NumberTargetProximityDomain;
- IndexTarget++)
- {
- Print (
- L" %5d",
- LatencyBandwidthMatrix[TargetStartOffset + IndexTarget]
- );
- } // for Target
- Print (L"\n");
- TargetStartOffset += (*NumberTargetProximityDomain);
- } // for Initiator
- Print (L"\n");
- } else {
- // Display the latency/bandwidth matrix as a list
- UnicodeSPrint (
- Buffer,
- sizeof (Buffer),
- SecondBuffer,
- L" [%d][%d]"
- );
- TargetStartOffset = 0;
- for (IndexInitiator = 0;
- IndexInitiator < *NumberInitiatorProximityDomain;
- IndexInitiator++)
- {
- for (IndexTarget = 0;
- IndexTarget < *NumberTargetProximityDomain;
- IndexTarget++)
- {
- UnicodeSPrint (
- SecondBuffer,
- sizeof (SecondBuffer),
- Buffer,
- IndexInitiator,
- IndexTarget
- );
- PrintFieldName (4, SecondBuffer);
- Print (
- L"%d\n",
- LatencyBandwidthMatrix[TargetStartOffset + IndexTarget]
- );
- } // for Target
- TargetStartOffset += (*NumberTargetProximityDomain);
- } // for Initiator
- }
- }
- /**
- This function parses the Memory Side Cache Information Structure (Type 2).
- @param [in] Ptr Pointer to the start of the Memory Side Cache Information
- Structure data.
- @param [in] Length Length of the Memory Side Cache Information Structure.
- **/
- STATIC
- VOID
- DumpMsci (
- IN UINT8 *Ptr,
- IN UINT32 Length
- )
- {
- CONST UINT16 *SMBIOSHandlesList;
- CHAR16 Buffer[OUTPUT_FIELD_COLUMN_WIDTH];
- UINT32 Offset;
- UINT16 Index;
- Offset = ParseAcpi (
- TRUE,
- 2,
- "Memory Side Cache Information Structure",
- Ptr,
- Length,
- PARSER_PARAMS (MemSideCacheInfoParser)
- );
- // Check if the values used to control the parsing logic have been
- // successfully read.
- if (NumberSMBIOSHandles == NULL) {
- IncrementErrorCount ();
- Print (
- L"ERROR: Insufficient remaining table buffer length to read the " \
- L"MSCI structure header. Length = %d.\n",
- Length
- );
- return;
- }
- if ((*NumberSMBIOSHandles * sizeof (UINT16)) > (Length - Offset)) {
- IncrementErrorCount ();
- Print (
- L"ERROR: Invalid Number of SMBIOS Handles. SMBIOSHandlesCount = %d." \
- L"RemainingBufferLength = %d.\n",
- *NumberSMBIOSHandles,
- Length - Offset
- );
- return;
- }
- SMBIOSHandlesList = (UINT16 *)(Ptr + Offset);
- for (Index = 0; Index < *NumberSMBIOSHandles; Index++) {
- UnicodeSPrint (
- Buffer,
- sizeof (Buffer),
- L"SMBIOS Handles [%d]",
- Index
- );
- PrintFieldName (4, Buffer);
- Print (
- L"0x%x\n",
- SMBIOSHandlesList[Index]
- );
- }
- }
- /**
- This function parses the ACPI HMAT table.
- When trace is enabled this function parses the HMAT table and
- traces the ACPI table fields.
- This function parses the following HMAT structures:
- - Memory Proximity Domain Attributes Structure (Type 0)
- - System Locality Latency and Bandwidth Info Structure (Type 1)
- - Memory Side Cache Info structure (Type 2)
- This function also performs validation of the ACPI table fields.
- @param [in] Trace If TRUE, trace the ACPI fields.
- @param [in] Ptr Pointer to the start of the buffer.
- @param [in] AcpiTableLength Length of the ACPI table.
- @param [in] AcpiTableRevision Revision of the ACPI table.
- **/
- VOID
- EFIAPI
- ParseAcpiHmat (
- IN BOOLEAN Trace,
- IN UINT8 *Ptr,
- IN UINT32 AcpiTableLength,
- IN UINT8 AcpiTableRevision
- )
- {
- UINT32 Offset;
- UINT8 *HmatStructurePtr;
- if (!Trace) {
- return;
- }
- Offset = ParseAcpi (
- Trace,
- 0,
- "HMAT",
- Ptr,
- AcpiTableLength,
- PARSER_PARAMS (HmatParser)
- );
- HmatStructurePtr = Ptr + Offset;
- while (Offset < AcpiTableLength) {
- // Parse HMAT Structure Header to obtain Type and Length.
- ParseAcpi (
- FALSE,
- 0,
- NULL,
- HmatStructurePtr,
- AcpiTableLength - Offset,
- PARSER_PARAMS (HmatStructureHeaderParser)
- );
- // Check if the values used to control the parsing logic have been
- // successfully read.
- if ((HmatStructureType == NULL) ||
- (HmatStructureLength == NULL))
- {
- IncrementErrorCount ();
- Print (
- L"ERROR: Insufficient remaining table buffer length to read the " \
- L"HMAT structure header. Length = %d.\n",
- AcpiTableLength - Offset
- );
- return;
- }
- // Validate HMAT Structure length.
- if ((*HmatStructureLength == 0) ||
- ((Offset + (*HmatStructureLength)) > AcpiTableLength))
- {
- IncrementErrorCount ();
- Print (
- L"ERROR: Invalid HMAT Structure length. " \
- L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
- *HmatStructureLength,
- Offset,
- AcpiTableLength
- );
- return;
- }
- switch (*HmatStructureType) {
- case EFI_ACPI_6_4_HMAT_TYPE_MEMORY_PROXIMITY_DOMAIN_ATTRIBUTES:
- DumpMpda (
- HmatStructurePtr,
- *HmatStructureLength
- );
- break;
- case EFI_ACPI_6_4_HMAT_TYPE_SYSTEM_LOCALITY_LATENCY_AND_BANDWIDTH_INFO:
- DumpSllbi (
- HmatStructurePtr,
- *HmatStructureLength
- );
- break;
- case EFI_ACPI_6_4_HMAT_TYPE_MEMORY_SIDE_CACHE_INFO:
- DumpMsci (
- HmatStructurePtr,
- *HmatStructureLength
- );
- break;
- default:
- IncrementErrorCount ();
- Print (
- L"ERROR: Unknown HMAT structure:"
- L" Type = %d, Length = %d\n",
- *HmatStructureType,
- *HmatStructureLength
- );
- break;
- } // switch
- HmatStructurePtr += *HmatStructureLength;
- Offset += *HmatStructureLength;
- } // while
- }
|