1 /*******************************************************************************
   2  *
   3  * Module Name: dbstats - Generation and display of ACPI table statistics
   4  *
   5  ******************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, Intel Corp.
   9  * All rights reserved.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions, and the following disclaimer,
  16  *    without modification.
  17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18  *    substantially similar to the "NO WARRANTY" disclaimer below
  19  *    ("Disclaimer") and any redistribution must be conditioned upon
  20  *    including a substantially similar Disclaimer requirement for further
  21  *    binary redistribution.
  22  * 3. Neither the names of the above-listed copyright holders nor the names
  23  *    of any contributors may be used to endorse or promote products derived
  24  *    from this software without specific prior written permission.
  25  *
  26  * Alternatively, this software may be distributed under the terms of the
  27  * GNU General Public License ("GPL") version 2 as published by the Free
  28  * Software Foundation.
  29  *
  30  * NO WARRANTY
  31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41  * POSSIBILITY OF SUCH DAMAGES.
  42  */
  43 
  44 
  45 #include "acpi.h"
  46 #include "accommon.h"
  47 #include "acdebug.h"
  48 #include "acnamesp.h"
  49 
  50 #ifdef ACPI_DEBUGGER
  51 
  52 #define _COMPONENT          ACPI_CA_DEBUGGER
  53         ACPI_MODULE_NAME    ("dbstats")
  54 
  55 /* Local prototypes */
  56 
  57 static void
  58 AcpiDbCountNamespaceObjects (
  59     void);
  60 
  61 static void
  62 AcpiDbEnumerateObject (
  63     ACPI_OPERAND_OBJECT     *ObjDesc);
  64 
  65 static ACPI_STATUS
  66 AcpiDbClassifyOneObject (
  67     ACPI_HANDLE             ObjHandle,
  68     UINT32                  NestingLevel,
  69     void                    *Context,
  70     void                    **ReturnValue);
  71 
  72 #if defined ACPI_DBG_TRACK_ALLOCATIONS || defined ACPI_USE_LOCAL_CACHE
  73 static void
  74 AcpiDbListInfo (
  75     ACPI_MEMORY_LIST        *List);
  76 #endif
  77 
  78 
  79 /*
  80  * Statistics subcommands
  81  */
  82 static ACPI_DB_ARGUMENT_INFO    AcpiDbStatTypes [] =
  83 {
  84     {"ALLOCATIONS"},
  85     {"OBJECTS"},
  86     {"MEMORY"},
  87     {"MISC"},
  88     {"TABLES"},
  89     {"SIZES"},
  90     {"STACK"},
  91     {NULL}           /* Must be null terminated */
  92 };
  93 
  94 #define CMD_STAT_ALLOCATIONS     0
  95 #define CMD_STAT_OBJECTS         1
  96 #define CMD_STAT_MEMORY          2
  97 #define CMD_STAT_MISC            3
  98 #define CMD_STAT_TABLES          4
  99 #define CMD_STAT_SIZES           5
 100 #define CMD_STAT_STACK           6
 101 
 102 
 103 #if defined ACPI_DBG_TRACK_ALLOCATIONS || defined ACPI_USE_LOCAL_CACHE
 104 /*******************************************************************************
 105  *
 106  * FUNCTION:    AcpiDbListInfo
 107  *
 108  * PARAMETERS:  List            - Memory list/cache to be displayed
 109  *
 110  * RETURN:      None
 111  *
 112  * DESCRIPTION: Display information about the input memory list or cache.
 113  *
 114  ******************************************************************************/
 115 
 116 static void
 117 AcpiDbListInfo (
 118     ACPI_MEMORY_LIST        *List)
 119 {
 120 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
 121     UINT32                  Outstanding;
 122 #endif
 123 
 124     AcpiOsPrintf ("\n%s\n", List->ListName);
 125 
 126     /* MaxDepth > 0 indicates a cache object */
 127 
 128     if (List->MaxDepth > 0)
 129     {
 130         AcpiOsPrintf (
 131             "    Cache: [Depth    MaxD Avail  Size]                %8.2X %8.2X %8.2X %8.2X\n",
 132             List->CurrentDepth,
 133             List->MaxDepth,
 134             List->MaxDepth - List->CurrentDepth,
 135             (List->CurrentDepth * List->ObjectSize));
 136     }
 137 
 138 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
 139     if (List->MaxDepth > 0)
 140     {
 141         AcpiOsPrintf (
 142             "    Cache: [Requests Hits Misses ObjSize]             %8.2X %8.2X %8.2X %8.2X\n",
 143             List->Requests,
 144             List->Hits,
 145             List->Requests - List->Hits,
 146             List->ObjectSize);
 147     }
 148 
 149     Outstanding = AcpiDbGetCacheInfo (List);
 150 
 151     if (List->ObjectSize)
 152     {
 153         AcpiOsPrintf (
 154             "    Mem:   [Alloc    Free Max    CurSize Outstanding] %8.2X %8.2X %8.2X %8.2X %8.2X\n",
 155             List->TotalAllocated,
 156             List->TotalFreed,
 157             List->MaxOccupied,
 158             Outstanding * List->ObjectSize,
 159             Outstanding);
 160     }
 161     else
 162     {
 163         AcpiOsPrintf (
 164             "    Mem:   [Alloc Free Max CurSize Outstanding Total] %8.2X %8.2X %8.2X %8.2X %8.2X %8.2X\n",
 165             List->TotalAllocated,
 166             List->TotalFreed,
 167             List->MaxOccupied,
 168             List->CurrentTotalSize,
 169             Outstanding,
 170             List->TotalSize);
 171     }
 172 #endif
 173 }
 174 #endif
 175 
 176 
 177 /*******************************************************************************
 178  *
 179  * FUNCTION:    AcpiDbEnumerateObject
 180  *
 181  * PARAMETERS:  ObjDesc             - Object to be counted
 182  *
 183  * RETURN:      None
 184  *
 185  * DESCRIPTION: Add this object to the global counts, by object type.
 186  *              Limited recursion handles subobjects and packages, and this
 187  *              is probably acceptable within the AML debugger only.
 188  *
 189  ******************************************************************************/
 190 
 191 static void
 192 AcpiDbEnumerateObject (
 193     ACPI_OPERAND_OBJECT     *ObjDesc)
 194 {
 195     UINT32                  i;
 196 
 197 
 198     if (!ObjDesc)
 199     {
 200         return;
 201     }
 202 
 203     /* Enumerate this object first */
 204 
 205     AcpiGbl_NumObjects++;
 206 
 207     if (ObjDesc->Common.Type > ACPI_TYPE_NS_NODE_MAX)
 208     {
 209         AcpiGbl_ObjTypeCountMisc++;
 210     }
 211     else
 212     {
 213         AcpiGbl_ObjTypeCount [ObjDesc->Common.Type]++;
 214     }
 215 
 216     /* Count the sub-objects */
 217 
 218     switch (ObjDesc->Common.Type)
 219     {
 220     case ACPI_TYPE_PACKAGE:
 221 
 222         for (i = 0; i < ObjDesc->Package.Count; i++)
 223         {
 224             AcpiDbEnumerateObject (ObjDesc->Package.Elements[i]);
 225         }
 226         break;
 227 
 228     case ACPI_TYPE_DEVICE:
 229 
 230         AcpiDbEnumerateObject (ObjDesc->Device.NotifyList[0]);
 231         AcpiDbEnumerateObject (ObjDesc->Device.NotifyList[1]);
 232         AcpiDbEnumerateObject (ObjDesc->Device.Handler);
 233         break;
 234 
 235     case ACPI_TYPE_BUFFER_FIELD:
 236 
 237         if (AcpiNsGetSecondaryObject (ObjDesc))
 238         {
 239             AcpiGbl_ObjTypeCount [ACPI_TYPE_BUFFER_FIELD]++;
 240         }
 241         break;
 242 
 243     case ACPI_TYPE_REGION:
 244 
 245         AcpiGbl_ObjTypeCount [ACPI_TYPE_LOCAL_REGION_FIELD ]++;
 246         AcpiDbEnumerateObject (ObjDesc->Region.Handler);
 247         break;
 248 
 249     case ACPI_TYPE_POWER:
 250 
 251         AcpiDbEnumerateObject (ObjDesc->PowerResource.NotifyList[0]);
 252         AcpiDbEnumerateObject (ObjDesc->PowerResource.NotifyList[1]);
 253         break;
 254 
 255     case ACPI_TYPE_PROCESSOR:
 256 
 257         AcpiDbEnumerateObject (ObjDesc->Processor.NotifyList[0]);
 258         AcpiDbEnumerateObject (ObjDesc->Processor.NotifyList[1]);
 259         AcpiDbEnumerateObject (ObjDesc->Processor.Handler);
 260         break;
 261 
 262     case ACPI_TYPE_THERMAL:
 263 
 264         AcpiDbEnumerateObject (ObjDesc->ThermalZone.NotifyList[0]);
 265         AcpiDbEnumerateObject (ObjDesc->ThermalZone.NotifyList[1]);
 266         AcpiDbEnumerateObject (ObjDesc->ThermalZone.Handler);
 267         break;
 268 
 269     default:
 270 
 271         break;
 272     }
 273 }
 274 
 275 
 276 /*******************************************************************************
 277  *
 278  * FUNCTION:    AcpiDbClassifyOneObject
 279  *
 280  * PARAMETERS:  Callback for WalkNamespace
 281  *
 282  * RETURN:      Status
 283  *
 284  * DESCRIPTION: Enumerate both the object descriptor (including subobjects) and
 285  *              the parent namespace node.
 286  *
 287  ******************************************************************************/
 288 
 289 static ACPI_STATUS
 290 AcpiDbClassifyOneObject (
 291     ACPI_HANDLE             ObjHandle,
 292     UINT32                  NestingLevel,
 293     void                    *Context,
 294     void                    **ReturnValue)
 295 {
 296     ACPI_NAMESPACE_NODE     *Node;
 297     ACPI_OPERAND_OBJECT     *ObjDesc;
 298     UINT32                  Type;
 299 
 300 
 301     AcpiGbl_NumNodes++;
 302 
 303     Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
 304     ObjDesc = AcpiNsGetAttachedObject (Node);
 305 
 306     AcpiDbEnumerateObject (ObjDesc);
 307 
 308     Type = Node->Type;
 309     if (Type > ACPI_TYPE_NS_NODE_MAX)
 310     {
 311         AcpiGbl_NodeTypeCountMisc++;
 312     }
 313     else
 314     {
 315         AcpiGbl_NodeTypeCount [Type]++;
 316     }
 317 
 318     return (AE_OK);
 319 
 320 
 321 #ifdef ACPI_FUTURE_IMPLEMENTATION
 322 
 323     /* TBD: These need to be counted during the initial parsing phase */
 324 
 325     if (AcpiPsIsNamedOp (Op->Opcode))
 326     {
 327         NumNodes++;
 328     }
 329 
 330     if (IsMethod)
 331     {
 332         NumMethodElements++;
 333     }
 334 
 335     NumGrammarElements++;
 336     Op = AcpiPsGetDepthNext (Root, Op);
 337 
 338     SizeOfParseTree   = (NumGrammarElements - NumMethodElements) *
 339                             (UINT32) sizeof (ACPI_PARSE_OBJECT);
 340     SizeOfMethodTrees = NumMethodElements * (UINT32) sizeof (ACPI_PARSE_OBJECT);
 341     SizeOfNodeEntries = NumNodes * (UINT32) sizeof (ACPI_NAMESPACE_NODE);
 342     SizeOfAcpiObjects = NumNodes * (UINT32) sizeof (ACPI_OPERAND_OBJECT);
 343 #endif
 344 }
 345 
 346 
 347 /*******************************************************************************
 348  *
 349  * FUNCTION:    AcpiDbCountNamespaceObjects
 350  *
 351  * PARAMETERS:  None
 352  *
 353  * RETURN:      None
 354  *
 355  * DESCRIPTION: Count and classify the entire namespace, including all
 356  *              namespace nodes and attached objects.
 357  *
 358  ******************************************************************************/
 359 
 360 static void
 361 AcpiDbCountNamespaceObjects (
 362     void)
 363 {
 364     UINT32                  i;
 365 
 366 
 367     AcpiGbl_NumNodes = 0;
 368     AcpiGbl_NumObjects = 0;
 369 
 370     AcpiGbl_ObjTypeCountMisc = 0;
 371     for (i = 0; i < (ACPI_TYPE_NS_NODE_MAX -1); i++)
 372     {
 373         AcpiGbl_ObjTypeCount [i] = 0;
 374         AcpiGbl_NodeTypeCount [i] = 0;
 375     }
 376 
 377     (void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
 378                 ACPI_UINT32_MAX, FALSE, AcpiDbClassifyOneObject, NULL, NULL, NULL);
 379 }
 380 
 381 
 382 /*******************************************************************************
 383  *
 384  * FUNCTION:    AcpiDbDisplayStatistics
 385  *
 386  * PARAMETERS:  TypeArg         - Subcommand
 387  *
 388  * RETURN:      Status
 389  *
 390  * DESCRIPTION: Display various statistics
 391  *
 392  ******************************************************************************/
 393 
 394 ACPI_STATUS
 395 AcpiDbDisplayStatistics (
 396     char                    *TypeArg)
 397 {
 398     UINT32                  i;
 399     UINT32                  Temp;
 400 
 401 
 402     AcpiUtStrupr (TypeArg);
 403     Temp = AcpiDbMatchArgument (TypeArg, AcpiDbStatTypes);
 404     if (Temp == ACPI_TYPE_NOT_FOUND)
 405     {
 406         AcpiOsPrintf ("Invalid or unsupported argument\n");
 407         return (AE_OK);
 408     }
 409 
 410 
 411     switch (Temp)
 412     {
 413     case CMD_STAT_ALLOCATIONS:
 414 
 415 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
 416         AcpiUtDumpAllocationInfo ();
 417 #endif
 418         break;
 419 
 420     case CMD_STAT_TABLES:
 421 
 422         AcpiOsPrintf ("ACPI Table Information (not implemented):\n\n");
 423         break;
 424 
 425     case CMD_STAT_OBJECTS:
 426 
 427         AcpiDbCountNamespaceObjects ();
 428 
 429         AcpiOsPrintf ("\nObjects defined in the current namespace:\n\n");
 430 
 431         AcpiOsPrintf ("%16.16s %10.10s %10.10s\n",
 432             "ACPI_TYPE", "NODES", "OBJECTS");
 433 
 434         for (i = 0; i < ACPI_TYPE_NS_NODE_MAX; i++)
 435         {
 436             AcpiOsPrintf ("%16.16s % 10ld% 10ld\n", AcpiUtGetTypeName (i),
 437                 AcpiGbl_NodeTypeCount [i], AcpiGbl_ObjTypeCount [i]);
 438         }
 439         AcpiOsPrintf ("%16.16s % 10ld% 10ld\n", "Misc/Unknown",
 440             AcpiGbl_NodeTypeCountMisc, AcpiGbl_ObjTypeCountMisc);
 441 
 442         AcpiOsPrintf ("%16.16s % 10ld% 10ld\n", "TOTALS:",
 443             AcpiGbl_NumNodes, AcpiGbl_NumObjects);
 444         break;
 445 
 446     case CMD_STAT_MEMORY:
 447 
 448 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
 449         AcpiOsPrintf ("\n----Object Statistics (all in hex)---------\n");
 450 
 451         AcpiDbListInfo (AcpiGbl_GlobalList);
 452         AcpiDbListInfo (AcpiGbl_NsNodeList);
 453 #endif
 454 
 455 #ifdef ACPI_USE_LOCAL_CACHE
 456         AcpiOsPrintf ("\n----Cache Statistics (all in hex)---------\n");
 457         AcpiDbListInfo (AcpiGbl_OperandCache);
 458         AcpiDbListInfo (AcpiGbl_PsNodeCache);
 459         AcpiDbListInfo (AcpiGbl_PsNodeExtCache);
 460         AcpiDbListInfo (AcpiGbl_StateCache);
 461 #endif
 462 
 463         break;
 464 
 465     case CMD_STAT_MISC:
 466 
 467         AcpiOsPrintf ("\nMiscellaneous Statistics:\n\n");
 468         AcpiOsPrintf ("Calls to AcpiPsFind:..  ........% 7ld\n",
 469             AcpiGbl_PsFindCount);
 470         AcpiOsPrintf ("Calls to AcpiNsLookup:..........% 7ld\n",
 471             AcpiGbl_NsLookupCount);
 472 
 473         AcpiOsPrintf ("\n");
 474 
 475         AcpiOsPrintf ("Mutex usage:\n\n");
 476         for (i = 0; i < ACPI_NUM_MUTEX; i++)
 477         {
 478             AcpiOsPrintf ("%-28s:       % 7ld\n",
 479                 AcpiUtGetMutexName (i), AcpiGbl_MutexInfo[i].UseCount);
 480         }
 481         break;
 482 
 483     case CMD_STAT_SIZES:
 484 
 485         AcpiOsPrintf ("\nInternal object sizes:\n\n");
 486 
 487         AcpiOsPrintf ("Common           %3d\n", sizeof (ACPI_OBJECT_COMMON));
 488         AcpiOsPrintf ("Number           %3d\n", sizeof (ACPI_OBJECT_INTEGER));
 489         AcpiOsPrintf ("String           %3d\n", sizeof (ACPI_OBJECT_STRING));
 490         AcpiOsPrintf ("Buffer           %3d\n", sizeof (ACPI_OBJECT_BUFFER));
 491         AcpiOsPrintf ("Package          %3d\n", sizeof (ACPI_OBJECT_PACKAGE));
 492         AcpiOsPrintf ("BufferField      %3d\n", sizeof (ACPI_OBJECT_BUFFER_FIELD));
 493         AcpiOsPrintf ("Device           %3d\n", sizeof (ACPI_OBJECT_DEVICE));
 494         AcpiOsPrintf ("Event            %3d\n", sizeof (ACPI_OBJECT_EVENT));
 495         AcpiOsPrintf ("Method           %3d\n", sizeof (ACPI_OBJECT_METHOD));
 496         AcpiOsPrintf ("Mutex            %3d\n", sizeof (ACPI_OBJECT_MUTEX));
 497         AcpiOsPrintf ("Region           %3d\n", sizeof (ACPI_OBJECT_REGION));
 498         AcpiOsPrintf ("PowerResource    %3d\n", sizeof (ACPI_OBJECT_POWER_RESOURCE));
 499         AcpiOsPrintf ("Processor        %3d\n", sizeof (ACPI_OBJECT_PROCESSOR));
 500         AcpiOsPrintf ("ThermalZone      %3d\n", sizeof (ACPI_OBJECT_THERMAL_ZONE));
 501         AcpiOsPrintf ("RegionField      %3d\n", sizeof (ACPI_OBJECT_REGION_FIELD));
 502         AcpiOsPrintf ("BankField        %3d\n", sizeof (ACPI_OBJECT_BANK_FIELD));
 503         AcpiOsPrintf ("IndexField       %3d\n", sizeof (ACPI_OBJECT_INDEX_FIELD));
 504         AcpiOsPrintf ("Reference        %3d\n", sizeof (ACPI_OBJECT_REFERENCE));
 505         AcpiOsPrintf ("Notify           %3d\n", sizeof (ACPI_OBJECT_NOTIFY_HANDLER));
 506         AcpiOsPrintf ("AddressSpace     %3d\n", sizeof (ACPI_OBJECT_ADDR_HANDLER));
 507         AcpiOsPrintf ("Extra            %3d\n", sizeof (ACPI_OBJECT_EXTRA));
 508         AcpiOsPrintf ("Data             %3d\n", sizeof (ACPI_OBJECT_DATA));
 509 
 510         AcpiOsPrintf ("\n");
 511 
 512         AcpiOsPrintf ("ParseObject      %3d\n", sizeof (ACPI_PARSE_OBJ_COMMON));
 513         AcpiOsPrintf ("ParseObjectNamed %3d\n", sizeof (ACPI_PARSE_OBJ_NAMED));
 514         AcpiOsPrintf ("ParseObjectAsl   %3d\n", sizeof (ACPI_PARSE_OBJ_ASL));
 515         AcpiOsPrintf ("OperandObject    %3d\n", sizeof (ACPI_OPERAND_OBJECT));
 516         AcpiOsPrintf ("NamespaceNode    %3d\n", sizeof (ACPI_NAMESPACE_NODE));
 517         AcpiOsPrintf ("AcpiObject       %3d\n", sizeof (ACPI_OBJECT));
 518 
 519         AcpiOsPrintf ("\n");
 520 
 521         AcpiOsPrintf ("Generic State    %3d\n", sizeof (ACPI_GENERIC_STATE));
 522         AcpiOsPrintf ("Common State     %3d\n", sizeof (ACPI_COMMON_STATE));
 523         AcpiOsPrintf ("Control State    %3d\n", sizeof (ACPI_CONTROL_STATE));
 524         AcpiOsPrintf ("Update State     %3d\n", sizeof (ACPI_UPDATE_STATE));
 525         AcpiOsPrintf ("Scope State      %3d\n", sizeof (ACPI_SCOPE_STATE));
 526         AcpiOsPrintf ("Parse Scope      %3d\n", sizeof (ACPI_PSCOPE_STATE));
 527         AcpiOsPrintf ("Package State    %3d\n", sizeof (ACPI_PKG_STATE));
 528         AcpiOsPrintf ("Thread State     %3d\n", sizeof (ACPI_THREAD_STATE));
 529         AcpiOsPrintf ("Result Values    %3d\n", sizeof (ACPI_RESULT_VALUES));
 530         AcpiOsPrintf ("Notify Info      %3d\n", sizeof (ACPI_NOTIFY_INFO));
 531         break;
 532 
 533     case CMD_STAT_STACK:
 534 #if defined(ACPI_DEBUG_OUTPUT)
 535 
 536         Temp = (UINT32) ACPI_PTR_DIFF (AcpiGbl_EntryStackPointer, AcpiGbl_LowestStackPointer);
 537 
 538         AcpiOsPrintf ("\nSubsystem Stack Usage:\n\n");
 539         AcpiOsPrintf ("Entry Stack Pointer          %p\n", AcpiGbl_EntryStackPointer);
 540         AcpiOsPrintf ("Lowest Stack Pointer         %p\n", AcpiGbl_LowestStackPointer);
 541         AcpiOsPrintf ("Stack Use                    %X (%u)\n", Temp, Temp);
 542         AcpiOsPrintf ("Deepest Procedure Nesting    %u\n", AcpiGbl_DeepestNesting);
 543 #endif
 544         break;
 545 
 546     default:
 547 
 548         break;
 549     }
 550 
 551     AcpiOsPrintf ("\n");
 552     return (AE_OK);
 553 }
 554 
 555 #endif /* ACPI_DEBUGGER  */