From: Marc Moisson-Franckhauser <marc.moisson-franckhau...@arm.com> Bugzilla: 3378 (https://bugzilla.tianocore.org/show_bug.cgi?id=3378)
This generates a dot file from the PPTT table that can be used to visualise the topology of the CPUs and Caches. Signed-off-by: Marc Moisson-Franckhauser <marc.moisson-franckhau...@arm.com> Signed-off-by: Joey Gouly <joey.go...@arm.com> --- ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c | 240 ++++++++++++++++++-- 1 file changed, 218 insertions(+), 22 deletions(-) diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c index 538b6a69350d75ccbf36b86fff115255e77437c7..b52bd532b846b9cec0ca315b043beff95df40bd5 100644 --- a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c @@ -15,11 +15,23 @@ #include "AcpiView.h" #include "AcpiViewConfig.h" #include "PpttParser.h" +#include "DotGenerator.h" // Local variables STATIC CONST UINT8* ProcessorTopologyStructureType; STATIC CONST UINT8* ProcessorTopologyStructureLength; + STATIC CONST UINT32* NumberOfPrivateResources; +STATIC CONST UINT32* ProcessorHierarchyParent; +STATIC CONST EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR_FLAGS* ProcStructFlags; +STATIC CONST UINT32* NextLevelOfCache; +STATIC CONST EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE_ATTRIBUTES* CacheAttributes; +STATIC CONST UINT32* CacheSize; + +STATIC CONST UINT8* PpttStartPointer; + +STATIC SHELL_FILE_HANDLE mDotFileHandle; + STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; /** @@ -198,8 +210,9 @@ STATIC CONST ACPI_PARSER ProcessorHierarchyNodeStructureParser[] = { {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL}, {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL}, - {L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, - {L"Parent", 4, 8, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Flags", 4, 4, L"0x%x", NULL, (VOID**)&ProcStructFlags, NULL, NULL}, + {L"Parent", 4, 8, L"0x%x", NULL, + (VOID**)&ProcessorHierarchyParent, NULL, NULL}, {L"ACPI Processor ID", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}, {L"Number of private resources", 4, 16, L"%d", NULL, (VOID**)&NumberOfPrivateResources, NULL, NULL} @@ -214,11 +227,13 @@ STATIC CONST ACPI_PARSER CacheTypeStructureParser[] = { {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL}, {L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, - {L"Next Level of Cache", 4, 8, L"0x%x", NULL, NULL, NULL, NULL}, - {L"Size", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Next Level of Cache", 4, 8, L"0x%x", NULL, + (VOID**)&NextLevelOfCache, NULL, NULL}, + {L"Size", 4, 12, L"0x%x", NULL, (VOID**)&CacheSize, NULL, NULL}, {L"Number of sets", 4, 16, L"%d", NULL, NULL, ValidateCacheNumberOfSets, NULL}, {L"Associativity", 1, 20, L"%d", NULL, NULL, ValidateCacheAssociativity, NULL}, - {L"Attributes", 1, 21, L"0x%x", NULL, NULL, ValidateCacheAttributes, NULL}, + {L"Attributes", 1, 21, L"0x%x", NULL, (VOID**)&CacheAttributes, + ValidateCacheAttributes, NULL}, {L"Line size", 2, 22, L"%d", NULL, NULL, ValidateCacheLineSize, NULL} }; @@ -257,6 +272,7 @@ DumpProcessorHierarchyNodeStructure ( UINT32 Offset; UINT32 Index; CHAR16 Buffer[OUTPUT_FIELD_COLUMN_WIDTH]; + CONST UINT8* TypePtr; Offset = ParseAcpi ( IS_TRACE_FLAG_SET (ParseFlags), @@ -291,26 +307,67 @@ DumpProcessorHierarchyNodeStructure ( return; } - Index = 0; + if (IS_GRAPH_FLAG_SET (ParseFlags)) { + if (ProcStructFlags->ProcessorIsAThread) { + UnicodeSPrint(Buffer, sizeof (Buffer), L"Thread"); + } else if (ProcStructFlags->NodeIsALeaf) { + UnicodeSPrint(Buffer, sizeof (Buffer), L"Core"); + } else if (ProcStructFlags->PhysicalPackage) { + UnicodeSPrint(Buffer, sizeof (Buffer), L"Physical\\nPackage"); + } else { + UnicodeSPrint(Buffer, sizeof (Buffer), L"Cluster"); + } + + DotAddNode ( + mDotFileHandle, + (UINT32)(Ptr - PpttStartPointer), + DOT_BOX_SQUARE | DOT_COLOR_BLUE | DOT_BOX_ADD_ID_TO_LABEL, + Buffer + ); + + // Add link to parent node. + if (*ProcessorHierarchyParent != 0) { + DotAddLink ( + mDotFileHandle, + (UINT32)(Ptr - PpttStartPointer), + *ProcessorHierarchyParent, + 0x0 + ); + } + } // Parse the specified number of private resource references or the Processor // Hierarchy Node length. Whichever is minimum. - while (Index < *NumberOfPrivateResources) { - UnicodeSPrint ( - Buffer, - sizeof (Buffer), - L"Private resources [%d]", - Index - ); + for (Index = 0; Index < *NumberOfPrivateResources; Index++) { + if (IS_TRACE_FLAG_SET (ParseFlags)) { + UnicodeSPrint ( + Buffer, + sizeof (Buffer), + L"Private resources [%d]", + Index + ); - PrintFieldName (4, Buffer); - Print ( - L"0x%x\n", - *((UINT32*)(Ptr + Offset)) - ); + PrintFieldName (4, Buffer); + Print ( + L"0x%x\n", + *((UINT32*)(Ptr + Offset)) + ); + } + + if (IS_GRAPH_FLAG_SET (ParseFlags)) { + TypePtr = PpttStartPointer + *((UINT32*)(Ptr + Offset)); + if (*TypePtr == EFI_ACPI_6_2_PPTT_TYPE_ID) { + continue; + } + DotAddLink ( + mDotFileHandle, + *((UINT32*)(Ptr + Offset)), + (UINT32)(Ptr - PpttStartPointer), + DOT_ARROW_RANK_REVERSE + ); + } Offset += sizeof (UINT32); - Index++; } } @@ -329,6 +386,8 @@ DumpCacheTypeStructure ( IN UINT8 Length ) { + CHAR16 LabelBuffer[64]; + ParseAcpi ( IS_TRACE_FLAG_SET (ParseFlags), 2, @@ -337,6 +396,88 @@ DumpCacheTypeStructure ( Length, PARSER_PARAMS (CacheTypeStructureParser) ); + + if (IS_GRAPH_FLAG_SET (ParseFlags)) { + // Create cache node + + // Start node label with type of cache + switch (CacheAttributes->CacheType) { + case EFI_ACPI_6_3_CACHE_ATTRIBUTES_CACHE_TYPE_DATA: + UnicodeSPrint ( + LabelBuffer, + sizeof (LabelBuffer), + L"D-Cache\\n" + ); + break; + case EFI_ACPI_6_3_CACHE_ATTRIBUTES_CACHE_TYPE_INSTRUCTION: + UnicodeSPrint ( + LabelBuffer, + sizeof (LabelBuffer), + L"I-Cache\\n" + ); + break; + default: + UnicodeSPrint ( + LabelBuffer, + sizeof (LabelBuffer), + L"Unified Cache\\n" + ); + } + + // Add size of cache to node label + if (((*CacheSize) & 0xfff00000) != 0) { + UnicodeSPrint ( + LabelBuffer, + sizeof (LabelBuffer), + L"%s%dMiB", + LabelBuffer, + *CacheSize >> 20 + ); + } + if ((*CacheSize & 0xffc00) != 0) { + UnicodeSPrint ( + LabelBuffer, + sizeof (LabelBuffer), + L"%s%dkiB", + LabelBuffer, + (*CacheSize >> 10) & 0x3ff + ); + } + if ((*CacheSize & 0x3ff) != 0) { + UnicodeSPrint ( + LabelBuffer, + sizeof (LabelBuffer), + L"%s%dB", + LabelBuffer, + *CacheSize & 0x3ff + ); + } + if (*CacheSize == 0) { + UnicodeSPrint ( + LabelBuffer, + sizeof (LabelBuffer), + L"%s0B", + LabelBuffer + ); + } + + //Add node to dot file + DotAddNode ( + mDotFileHandle, + (UINT32)(Ptr - PpttStartPointer), + DOT_BOX_SQUARE | DOT_COLOR_YELLOW | DOT_BOX_ADD_ID_TO_LABEL, + LabelBuffer + ); + + if (*NextLevelOfCache != 0) { + DotAddLink ( + mDotFileHandle, + *NextLevelOfCache, + (UINT32)(Ptr - PpttStartPointer), + DOT_ARROW_RANK_REVERSE | DOT_COLOR_GRAY + ); + } + } } /** @@ -390,13 +531,46 @@ ParseAcpiPptt ( IN UINT8 AcpiTableRevision ) { - UINT32 Offset; - UINT8* ProcessorTopologyStructurePtr; + EFI_STATUS Status; + UINT32 Offset; + UINT8* ProcessorTopologyStructurePtr; + CHAR16 Buffer[128]; + CHAR16 FileNameBuffer[MAX_FILE_NAME_LEN]; - if (!IS_TRACE_FLAG_SET (ParseFlags)) { + if (!IS_TRACE_FLAG_SET (ParseFlags) && + !IS_GRAPH_FLAG_SET (ParseFlags)) { return; } + if (IS_GRAPH_FLAG_SET (ParseFlags)) { + Status = GetNewFileName ( + L"PPTT", + L"dot", + FileNameBuffer, + sizeof (FileNameBuffer) + ); + + if (EFI_ERROR (Status)) { + Print ( + L"Error: Could not open dot file for PPTT table:\n" + L"Could not get a file name." + ); + // Abandonning creation of dot graph by unsetting the flag. + // We continue parsing in case trace is set. + ParseFlags &= ~PARSE_FLAGS_GRAPH; + } else { + mDotFileHandle = DotOpenNewFile (FileNameBuffer); + if (mDotFileHandle == NULL) { + Print (L"ERROR: Could not open dot file for PPTT table.\n"); + // Abandonning creation of dot graph by unsetting the flag. + // We continue parsing in case trace is set. + ParseFlags &= ~PARSE_FLAGS_GRAPH; + } + } + } + + PpttStartPointer = Ptr; + Offset = ParseAcpi ( IS_TRACE_FLAG_SET (ParseFlags), 0, @@ -406,6 +580,24 @@ ParseAcpiPptt ( PARSER_PARAMS (PpttParser) ); + if (*(AcpiHdrInfo.Revision) < 2 && + IS_GRAPH_FLAG_SET (ParseFlags)) { + Print (L"\nWARNING: Dot output may not be consistent for PPTT revisions < 2\n"); + UnicodeSPrint ( + Buffer, + sizeof (Buffer), + L"WARNING: PPTT table revision is %u.\\n" \ + L"Revisions lower than 2 might lead to incorrect labelling", + *(AcpiHdrInfo.Revision) + ); + DotAddNode ( + mDotFileHandle, + 0, + DOT_COLOR_RED | DOT_BOX_SQUARE, + Buffer + ); + } + ProcessorTopologyStructurePtr = Ptr + Offset; while (Offset < AcpiTableLength) { @@ -486,4 +678,8 @@ ParseAcpiPptt ( ProcessorTopologyStructurePtr += *ProcessorTopologyStructureLength; Offset += *ProcessorTopologyStructureLength; } // while + + if (IS_GRAPH_FLAG_SET (ParseFlags)) { + DotCloseFile (mDotFileHandle); + } } -- Guid("CE165669-3EF3-493F-B85D-6190EE5B9759") -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#74807): https://edk2.groups.io/g/devel/message/74807 Mute This Topic: https://groups.io/mt/82651819/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-