1 /*******************************************************************************
   2  *
   3  * Module Name: dbstats - Generation and display of ACPI table statistics
   4  *
   5  ******************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2011, 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 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.SystemNotify);
 231         AcpiDbEnumerateObject (ObjDesc->Device.DeviceNotify);
 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.SystemNotify);
 252         AcpiDbEnumerateObject (ObjDesc->PowerResource.DeviceNotify);
 253         break;
 254 
 255     case ACPI_TYPE_PROCESSOR:
 256 
 257         AcpiDbEnumerateObject (ObjDesc->Processor.SystemNotify);
 258         AcpiDbEnumerateObject (ObjDesc->Processor.DeviceNotify);
 259         AcpiDbEnumerateObject (ObjDesc->Processor.Handler);
 260         break;
 261 
 262     case ACPI_TYPE_THERMAL:
 263 
 264         AcpiDbEnumerateObject (ObjDesc->ThermalZone.SystemNotify);
 265         AcpiDbEnumerateObject (ObjDesc->ThermalZone.DeviceNotify);
 266         AcpiDbEnumerateObject (ObjDesc->ThermalZone.Handler);
 267         break;
 268 
 269     default:
 270         break;
 271     }
 272 }
 273 
 274 
 275 /*******************************************************************************
 276  *
 277  * FUNCTION:    AcpiDbClassifyOneObject
 278  *
 279  * PARAMETERS:  Callback for WalkNamespace
 280  *
 281  * RETURN:      Status
 282  *
 283  * DESCRIPTION: Enumerate both the object descriptor (including subobjects) and
 284  *              the parent namespace node.
 285  *
 286  ******************************************************************************/
 287 
 288 static ACPI_STATUS
 289 AcpiDbClassifyOneObject (
 290     ACPI_HANDLE             ObjHandle,
 291     UINT32                  NestingLevel,
 292     void                    *Context,
 293     void                    **ReturnValue)
 294 {
 295     ACPI_NAMESPACE_NODE     *Node;
 296     ACPI_OPERAND_OBJECT     *ObjDesc;
 297     UINT32                  Type;
 298 
 299 
 300     AcpiGbl_NumNodes++;
 301 
 302     Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
 303     ObjDesc = AcpiNsGetAttachedObject (Node);
 304 
 305     AcpiDbEnumerateObject (ObjDesc);
 306 
 307     Type = Node->Type;
 308     if (Type > ACPI_TYPE_NS_NODE_MAX)
 309     {
 310         AcpiGbl_NodeTypeCountMisc++;
 311     }
 312     else
 313     {
 314         AcpiGbl_NodeTypeCount [Type]++;
 315     }
 316 
 317     return AE_OK;
 318 
 319 
 320 #ifdef ACPI_FUTURE_IMPLEMENTATION
 321 
 322     /* TBD: These need to be counted during the initial parsing phase */
 323 
 324     if (AcpiPsIsNamedOp (Op->Opcode))
 325     {
 326         NumNodes++;
 327     }
 328 
 329     if (IsMethod)
 330     {
 331         NumMethodElements++;
 332     }
 333 
 334     NumGrammarElements++;
 335     Op = AcpiPsGetDepthNext (Root, Op);
 336 
 337     SizeOfParseTree   = (NumGrammarElements - NumMethodElements) *
 338                             (UINT32) sizeof (ACPI_PARSE_OBJECT);
 339     SizeOfMethodTrees = NumMethodElements * (UINT32) sizeof (ACPI_PARSE_OBJECT);
 340     SizeOfNodeEntries = NumNodes * (UINT32) sizeof (ACPI_NAMESPACE_NODE);
 341     SizeOfAcpiObjects = NumNodes * (UINT32) sizeof (ACPI_OPERAND_OBJECT);
 342 #endif
 343 }
 344 
 345 
 346 /*******************************************************************************
 347  *
 348  * FUNCTION:    AcpiDbCountNamespaceObjects
 349  *
 350  * PARAMETERS:  None
 351  *
 352  * RETURN:      None
 353  *
 354  * DESCRIPTION: Count and classify the entire namespace, including all
 355  *              namespace nodes and attached objects.
 356  *
 357  ******************************************************************************/
 358 
 359 static void
 360 AcpiDbCountNamespaceObjects (
 361     void)
 362 {
 363     UINT32                  i;
 364 
 365 
 366     AcpiGbl_NumNodes = 0;
 367     AcpiGbl_NumObjects = 0;
 368 
 369     AcpiGbl_ObjTypeCountMisc = 0;
 370     for (i = 0; i < (ACPI_TYPE_NS_NODE_MAX -1); i++)
 371     {
 372         AcpiGbl_ObjTypeCount [i] = 0;
 373         AcpiGbl_NodeTypeCount [i] = 0;
 374     }
 375 
 376     (void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
 377                 ACPI_UINT32_MAX, FALSE, AcpiDbClassifyOneObject, NULL, NULL, NULL);
 378 }
 379 
 380 
 381 /*******************************************************************************
 382  *
 383  * FUNCTION:    AcpiDbDisplayStatistics
 384  *
 385  * PARAMETERS:  TypeArg         - Subcommand
 386  *
 387  * RETURN:      Status
 388  *
 389  * DESCRIPTION: Display various statistics
 390  *
 391  ******************************************************************************/
 392 
 393 ACPI_STATUS
 394 AcpiDbDisplayStatistics (
 395     char                    *TypeArg)
 396 {
 397     UINT32                  i;
 398     UINT32                  Temp;
 399 
 400 
 401     if (!TypeArg)
 402     {
 403         AcpiOsPrintf ("The following subcommands are available:\n    ALLOCATIONS, OBJECTS, MEMORY, MISC, SIZES, TABLES\n");
 404         return (AE_OK);
 405     }
 406 
 407     AcpiUtStrupr (TypeArg);
 408     Temp = AcpiDbMatchArgument (TypeArg, AcpiDbStatTypes);
 409     if (Temp == (UINT32) -1)
 410     {
 411         AcpiOsPrintf ("Invalid or unsupported argument\n");
 412         return (AE_OK);
 413     }
 414 
 415 
 416     switch (Temp)
 417     {
 418     case CMD_STAT_ALLOCATIONS:
 419 
 420 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
 421         AcpiUtDumpAllocationInfo ();
 422 #endif
 423         break;
 424 
 425     case CMD_STAT_TABLES:
 426 
 427         AcpiOsPrintf ("ACPI Table Information (not implemented):\n\n");
 428         break;
 429 
 430     case CMD_STAT_OBJECTS:
 431 
 432         AcpiDbCountNamespaceObjects ();
 433 
 434         AcpiOsPrintf ("\nObjects defined in the current namespace:\n\n");
 435 
 436         AcpiOsPrintf ("%16.16s %10.10s %10.10s\n",
 437             "ACPI_TYPE", "NODES", "OBJECTS");
 438 
 439         for (i = 0; i < ACPI_TYPE_NS_NODE_MAX; i++)
 440         {
 441             AcpiOsPrintf ("%16.16s % 10ld% 10ld\n", AcpiUtGetTypeName (i),
 442                 AcpiGbl_NodeTypeCount [i], AcpiGbl_ObjTypeCount [i]);
 443         }
 444         AcpiOsPrintf ("%16.16s % 10ld% 10ld\n", "Misc/Unknown",
 445             AcpiGbl_NodeTypeCountMisc, AcpiGbl_ObjTypeCountMisc);
 446 
 447         AcpiOsPrintf ("%16.16s % 10ld% 10ld\n", "TOTALS:",
 448             AcpiGbl_NumNodes, AcpiGbl_NumObjects);
 449         break;
 450 
 451     case CMD_STAT_MEMORY:
 452 
 453 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
 454         AcpiOsPrintf ("\n----Object Statistics (all in hex)---------\n");
 455 
 456         AcpiDbListInfo (AcpiGbl_GlobalList);
 457         AcpiDbListInfo (AcpiGbl_NsNodeList);
 458 #endif
 459 
 460 #ifdef ACPI_USE_LOCAL_CACHE
 461         AcpiOsPrintf ("\n----Cache Statistics (all in hex)---------\n");
 462         AcpiDbListInfo (AcpiGbl_OperandCache);
 463         AcpiDbListInfo (AcpiGbl_PsNodeCache);
 464         AcpiDbListInfo (AcpiGbl_PsNodeExtCache);
 465         AcpiDbListInfo (AcpiGbl_StateCache);
 466 #endif
 467 
 468         break;
 469 
 470     case CMD_STAT_MISC:
 471 
 472         AcpiOsPrintf ("\nMiscellaneous Statistics:\n\n");
 473         AcpiOsPrintf ("Calls to AcpiPsFind:..  ........% 7ld\n",
 474             AcpiGbl_PsFindCount);
 475         AcpiOsPrintf ("Calls to AcpiNsLookup:..........% 7ld\n",
 476             AcpiGbl_NsLookupCount);
 477 
 478         AcpiOsPrintf ("\n");
 479 
 480         AcpiOsPrintf ("Mutex usage:\n\n");
 481         for (i = 0; i < ACPI_NUM_MUTEX; i++)
 482         {
 483             AcpiOsPrintf ("%-28s:       % 7ld\n",
 484                 AcpiUtGetMutexName (i), AcpiGbl_MutexInfo[i].UseCount);
 485         }
 486         break;
 487 
 488 
 489     case CMD_STAT_SIZES:
 490 
 491         AcpiOsPrintf ("\nInternal object sizes:\n\n");
 492 
 493         AcpiOsPrintf ("Common           %3d\n", sizeof (ACPI_OBJECT_COMMON));
 494         AcpiOsPrintf ("Number           %3d\n", sizeof (ACPI_OBJECT_INTEGER));
 495         AcpiOsPrintf ("String           %3d\n", sizeof (ACPI_OBJECT_STRING));
 496         AcpiOsPrintf ("Buffer           %3d\n", sizeof (ACPI_OBJECT_BUFFER));
 497         AcpiOsPrintf ("Package          %3d\n", sizeof (ACPI_OBJECT_PACKAGE));
 498         AcpiOsPrintf ("BufferField      %3d\n", sizeof (ACPI_OBJECT_BUFFER_FIELD));
 499         AcpiOsPrintf ("Device           %3d\n", sizeof (ACPI_OBJECT_DEVICE));
 500         AcpiOsPrintf ("Event            %3d\n", sizeof (ACPI_OBJECT_EVENT));
 501         AcpiOsPrintf ("Method           %3d\n", sizeof (ACPI_OBJECT_METHOD));
 502         AcpiOsPrintf ("Mutex            %3d\n", sizeof (ACPI_OBJECT_MUTEX));
 503         AcpiOsPrintf ("Region           %3d\n", sizeof (ACPI_OBJECT_REGION));
 504         AcpiOsPrintf ("PowerResource    %3d\n", sizeof (ACPI_OBJECT_POWER_RESOURCE));
 505         AcpiOsPrintf ("Processor        %3d\n", sizeof (ACPI_OBJECT_PROCESSOR));
 506         AcpiOsPrintf ("ThermalZone      %3d\n", sizeof (ACPI_OBJECT_THERMAL_ZONE));
 507         AcpiOsPrintf ("RegionField      %3d\n", sizeof (ACPI_OBJECT_REGION_FIELD));
 508         AcpiOsPrintf ("BankField        %3d\n", sizeof (ACPI_OBJECT_BANK_FIELD));
 509         AcpiOsPrintf ("IndexField       %3d\n", sizeof (ACPI_OBJECT_INDEX_FIELD));
 510         AcpiOsPrintf ("Reference        %3d\n", sizeof (ACPI_OBJECT_REFERENCE));
 511         AcpiOsPrintf ("Notify           %3d\n", sizeof (ACPI_OBJECT_NOTIFY_HANDLER));
 512         AcpiOsPrintf ("AddressSpace     %3d\n", sizeof (ACPI_OBJECT_ADDR_HANDLER));
 513         AcpiOsPrintf ("Extra            %3d\n", sizeof (ACPI_OBJECT_EXTRA));
 514         AcpiOsPrintf ("Data             %3d\n", sizeof (ACPI_OBJECT_DATA));
 515 
 516         AcpiOsPrintf ("\n");
 517 
 518         AcpiOsPrintf ("ParseObject      %3d\n", sizeof (ACPI_PARSE_OBJ_COMMON));
 519         AcpiOsPrintf ("ParseObjectNamed %3d\n", sizeof (ACPI_PARSE_OBJ_NAMED));
 520         AcpiOsPrintf ("ParseObjectAsl   %3d\n", sizeof (ACPI_PARSE_OBJ_ASL));
 521         AcpiOsPrintf ("OperandObject    %3d\n", sizeof (ACPI_OPERAND_OBJECT));
 522         AcpiOsPrintf ("NamespaceNode    %3d\n", sizeof (ACPI_NAMESPACE_NODE));
 523         AcpiOsPrintf ("AcpiObject       %3d\n", sizeof (ACPI_OBJECT));
 524 
 525         break;
 526 
 527 
 528     case CMD_STAT_STACK:
 529 #if defined(ACPI_DEBUG_OUTPUT)
 530 
 531         Temp = (UINT32) ACPI_PTR_DIFF (AcpiGbl_EntryStackPointer, AcpiGbl_LowestStackPointer);
 532 
 533         AcpiOsPrintf ("\nSubsystem Stack Usage:\n\n");
 534         AcpiOsPrintf ("Entry Stack Pointer          %p\n", AcpiGbl_EntryStackPointer);
 535         AcpiOsPrintf ("Lowest Stack Pointer         %p\n", AcpiGbl_LowestStackPointer);
 536         AcpiOsPrintf ("Stack Use                    %X (%u)\n", Temp, Temp);
 537         AcpiOsPrintf ("Deepest Procedure Nesting    %u\n", AcpiGbl_DeepestNesting);
 538 #endif
 539         break;
 540 
 541     default:
 542         break;
 543     }
 544 
 545     AcpiOsPrintf ("\n");
 546     return (AE_OK);
 547 }
 548 
 549 #endif /* ACPI_DEBUGGER  */