1 /******************************************************************************* 2 * 3 * Module Name: dbstats - Generation and display of ACPI table statistics 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 #include "acpi.h" 45 #include "accommon.h" 46 #include "acdebug.h" 47 #include "acnamesp.h" 48 49 #ifdef ACPI_DEBUGGER 50 51 #define _COMPONENT ACPI_CA_DEBUGGER 52 ACPI_MODULE_NAME ("dbstats") 53 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] " 132 "%8.2X %8.2X %8.2X %8.2X\n", 133 List->CurrentDepth, 134 List->MaxDepth, 135 List->MaxDepth - List->CurrentDepth, 136 (List->CurrentDepth * List->ObjectSize)); 137 } 138 139 #ifdef ACPI_DBG_TRACK_ALLOCATIONS 140 if (List->MaxDepth > 0) 141 { 142 AcpiOsPrintf ( 143 " Cache: [Requests Hits Misses ObjSize] " 144 "%8.2X %8.2X %8.2X %8.2X\n", 145 List->Requests, 146 List->Hits, 147 List->Requests - List->Hits, 148 List->ObjectSize); 149 } 150 151 Outstanding = AcpiDbGetCacheInfo (List); 152 153 if (List->ObjectSize) 154 { 155 AcpiOsPrintf ( 156 " Mem: [Alloc Free Max CurSize Outstanding] " 157 "%8.2X %8.2X %8.2X %8.2X %8.2X\n", 158 List->TotalAllocated, 159 List->TotalFreed, 160 List->MaxOccupied, 161 Outstanding * List->ObjectSize, 162 Outstanding); 163 } 164 else 165 { 166 AcpiOsPrintf ( 167 " Mem: [Alloc Free Max CurSize Outstanding Total] " 168 "%8.2X %8.2X %8.2X %8.2X %8.2X %8.2X\n", 169 List->TotalAllocated, 170 List->TotalFreed, 171 List->MaxOccupied, 172 List->CurrentTotalSize, 173 Outstanding, 174 List->TotalSize); 175 } 176 #endif 177 } 178 #endif 179 180 181 /******************************************************************************* 182 * 183 * FUNCTION: AcpiDbEnumerateObject 184 * 185 * PARAMETERS: ObjDesc - Object to be counted 186 * 187 * RETURN: None 188 * 189 * DESCRIPTION: Add this object to the global counts, by object type. 190 * Limited recursion handles subobjects and packages, and this 191 * is probably acceptable within the AML debugger only. 192 * 193 ******************************************************************************/ 194 195 static void 196 AcpiDbEnumerateObject ( 197 ACPI_OPERAND_OBJECT *ObjDesc) 198 { 199 UINT32 i; 200 201 202 if (!ObjDesc) 203 { 204 return; 205 } 206 207 /* Enumerate this object first */ 208 209 AcpiGbl_NumObjects++; 210 211 if (ObjDesc->Common.Type > ACPI_TYPE_NS_NODE_MAX) 212 { 213 AcpiGbl_ObjTypeCountMisc++; 214 } 215 else 216 { 217 AcpiGbl_ObjTypeCount [ObjDesc->Common.Type]++; 218 } 219 220 /* Count the sub-objects */ 221 222 switch (ObjDesc->Common.Type) 223 { 224 case ACPI_TYPE_PACKAGE: 225 226 for (i = 0; i < ObjDesc->Package.Count; i++) 227 { 228 AcpiDbEnumerateObject (ObjDesc->Package.Elements[i]); 229 } 230 break; 231 232 case ACPI_TYPE_DEVICE: 233 234 AcpiDbEnumerateObject (ObjDesc->Device.NotifyList[0]); 235 AcpiDbEnumerateObject (ObjDesc->Device.NotifyList[1]); 236 AcpiDbEnumerateObject (ObjDesc->Device.Handler); 237 break; 238 239 case ACPI_TYPE_BUFFER_FIELD: 240 241 if (AcpiNsGetSecondaryObject (ObjDesc)) 242 { 243 AcpiGbl_ObjTypeCount [ACPI_TYPE_BUFFER_FIELD]++; 244 } 245 break; 246 247 case ACPI_TYPE_REGION: 248 249 AcpiGbl_ObjTypeCount [ACPI_TYPE_LOCAL_REGION_FIELD ]++; 250 AcpiDbEnumerateObject (ObjDesc->Region.Handler); 251 break; 252 253 case ACPI_TYPE_POWER: 254 255 AcpiDbEnumerateObject (ObjDesc->PowerResource.NotifyList[0]); 256 AcpiDbEnumerateObject (ObjDesc->PowerResource.NotifyList[1]); 257 break; 258 259 case ACPI_TYPE_PROCESSOR: 260 261 AcpiDbEnumerateObject (ObjDesc->Processor.NotifyList[0]); 262 AcpiDbEnumerateObject (ObjDesc->Processor.NotifyList[1]); 263 AcpiDbEnumerateObject (ObjDesc->Processor.Handler); 264 break; 265 266 case ACPI_TYPE_THERMAL: 267 268 AcpiDbEnumerateObject (ObjDesc->ThermalZone.NotifyList[0]); 269 AcpiDbEnumerateObject (ObjDesc->ThermalZone.NotifyList[1]); 270 AcpiDbEnumerateObject (ObjDesc->ThermalZone.Handler); 271 break; 272 273 default: 274 275 break; 276 } 277 } 278 279 280 /******************************************************************************* 281 * 282 * FUNCTION: AcpiDbClassifyOneObject 283 * 284 * PARAMETERS: Callback for WalkNamespace 285 * 286 * RETURN: Status 287 * 288 * DESCRIPTION: Enumerate both the object descriptor (including subobjects) and 289 * the parent namespace node. 290 * 291 ******************************************************************************/ 292 293 static ACPI_STATUS 294 AcpiDbClassifyOneObject ( 295 ACPI_HANDLE ObjHandle, 296 UINT32 NestingLevel, 297 void *Context, 298 void **ReturnValue) 299 { 300 ACPI_NAMESPACE_NODE *Node; 301 ACPI_OPERAND_OBJECT *ObjDesc; 302 UINT32 Type; 303 304 305 AcpiGbl_NumNodes++; 306 307 Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 308 ObjDesc = AcpiNsGetAttachedObject (Node); 309 310 AcpiDbEnumerateObject (ObjDesc); 311 312 Type = Node->Type; 313 if (Type > ACPI_TYPE_NS_NODE_MAX) 314 { 315 AcpiGbl_NodeTypeCountMisc++; 316 } 317 else 318 { 319 AcpiGbl_NodeTypeCount [Type]++; 320 } 321 322 return (AE_OK); 323 324 325 #ifdef ACPI_FUTURE_IMPLEMENTATION 326 327 /* TBD: These need to be counted during the initial parsing phase */ 328 329 if (AcpiPsIsNamedOp (Op->Opcode)) 330 { 331 NumNodes++; 332 } 333 334 if (IsMethod) 335 { 336 NumMethodElements++; 337 } 338 339 NumGrammarElements++; 340 Op = AcpiPsGetDepthNext (Root, Op); 341 342 SizeOfParseTree = (NumGrammarElements - NumMethodElements) * 343 (UINT32) sizeof (ACPI_PARSE_OBJECT); 344 SizeOfMethodTrees = NumMethodElements * (UINT32) sizeof (ACPI_PARSE_OBJECT); 345 SizeOfNodeEntries = NumNodes * (UINT32) sizeof (ACPI_NAMESPACE_NODE); 346 SizeOfAcpiObjects = NumNodes * (UINT32) sizeof (ACPI_OPERAND_OBJECT); 347 #endif 348 } 349 350 351 /******************************************************************************* 352 * 353 * FUNCTION: AcpiDbCountNamespaceObjects 354 * 355 * PARAMETERS: None 356 * 357 * RETURN: None 358 * 359 * DESCRIPTION: Count and classify the entire namespace, including all 360 * namespace nodes and attached objects. 361 * 362 ******************************************************************************/ 363 364 static void 365 AcpiDbCountNamespaceObjects ( 366 void) 367 { 368 UINT32 i; 369 370 371 AcpiGbl_NumNodes = 0; 372 AcpiGbl_NumObjects = 0; 373 374 AcpiGbl_ObjTypeCountMisc = 0; 375 for (i = 0; i < (ACPI_TYPE_NS_NODE_MAX -1); i++) 376 { 377 AcpiGbl_ObjTypeCount [i] = 0; 378 AcpiGbl_NodeTypeCount [i] = 0; 379 } 380 381 (void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 382 ACPI_UINT32_MAX, FALSE, AcpiDbClassifyOneObject, NULL, NULL, NULL); 383 } 384 385 386 /******************************************************************************* 387 * 388 * FUNCTION: AcpiDbDisplayStatistics 389 * 390 * PARAMETERS: TypeArg - Subcommand 391 * 392 * RETURN: Status 393 * 394 * DESCRIPTION: Display various statistics 395 * 396 ******************************************************************************/ 397 398 ACPI_STATUS 399 AcpiDbDisplayStatistics ( 400 char *TypeArg) 401 { 402 UINT32 i; 403 UINT32 Temp; 404 405 406 AcpiUtStrupr (TypeArg); 407 Temp = AcpiDbMatchArgument (TypeArg, AcpiDbStatTypes); 408 if (Temp == ACPI_TYPE_NOT_FOUND) 409 { 410 AcpiOsPrintf ("Invalid or unsupported argument\n"); 411 return (AE_OK); 412 } 413 414 415 switch (Temp) 416 { 417 case CMD_STAT_ALLOCATIONS: 418 419 #ifdef ACPI_DBG_TRACK_ALLOCATIONS 420 AcpiUtDumpAllocationInfo (); 421 #endif 422 break; 423 424 case CMD_STAT_TABLES: 425 426 AcpiOsPrintf ("ACPI Table Information (not implemented):\n\n"); 427 break; 428 429 case CMD_STAT_OBJECTS: 430 431 AcpiDbCountNamespaceObjects (); 432 433 AcpiOsPrintf ("\nObjects defined in the current namespace:\n\n"); 434 435 AcpiOsPrintf ("%16.16s %10.10s %10.10s\n", 436 "ACPI_TYPE", "NODES", "OBJECTS"); 437 438 for (i = 0; i < ACPI_TYPE_NS_NODE_MAX; i++) 439 { 440 AcpiOsPrintf ("%16.16s % 10ld% 10ld\n", AcpiUtGetTypeName (i), 441 AcpiGbl_NodeTypeCount [i], AcpiGbl_ObjTypeCount [i]); 442 } 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 case CMD_STAT_SIZES: 489 490 AcpiOsPrintf ("\nInternal object sizes:\n\n"); 491 492 AcpiOsPrintf ("Common %3d\n", sizeof (ACPI_OBJECT_COMMON)); 493 AcpiOsPrintf ("Number %3d\n", sizeof (ACPI_OBJECT_INTEGER)); 494 AcpiOsPrintf ("String %3d\n", sizeof (ACPI_OBJECT_STRING)); 495 AcpiOsPrintf ("Buffer %3d\n", sizeof (ACPI_OBJECT_BUFFER)); 496 AcpiOsPrintf ("Package %3d\n", sizeof (ACPI_OBJECT_PACKAGE)); 497 AcpiOsPrintf ("BufferField %3d\n", sizeof (ACPI_OBJECT_BUFFER_FIELD)); 498 AcpiOsPrintf ("Device %3d\n", sizeof (ACPI_OBJECT_DEVICE)); 499 AcpiOsPrintf ("Event %3d\n", sizeof (ACPI_OBJECT_EVENT)); 500 AcpiOsPrintf ("Method %3d\n", sizeof (ACPI_OBJECT_METHOD)); 501 AcpiOsPrintf ("Mutex %3d\n", sizeof (ACPI_OBJECT_MUTEX)); 502 AcpiOsPrintf ("Region %3d\n", sizeof (ACPI_OBJECT_REGION)); 503 AcpiOsPrintf ("PowerResource %3d\n", sizeof (ACPI_OBJECT_POWER_RESOURCE)); 504 AcpiOsPrintf ("Processor %3d\n", sizeof (ACPI_OBJECT_PROCESSOR)); 505 AcpiOsPrintf ("ThermalZone %3d\n", sizeof (ACPI_OBJECT_THERMAL_ZONE)); 506 AcpiOsPrintf ("RegionField %3d\n", sizeof (ACPI_OBJECT_REGION_FIELD)); 507 AcpiOsPrintf ("BankField %3d\n", sizeof (ACPI_OBJECT_BANK_FIELD)); 508 AcpiOsPrintf ("IndexField %3d\n", sizeof (ACPI_OBJECT_INDEX_FIELD)); 509 AcpiOsPrintf ("Reference %3d\n", sizeof (ACPI_OBJECT_REFERENCE)); 510 AcpiOsPrintf ("Notify %3d\n", sizeof (ACPI_OBJECT_NOTIFY_HANDLER)); 511 AcpiOsPrintf ("AddressSpace %3d\n", sizeof (ACPI_OBJECT_ADDR_HANDLER)); 512 AcpiOsPrintf ("Extra %3d\n", sizeof (ACPI_OBJECT_EXTRA)); 513 AcpiOsPrintf ("Data %3d\n", sizeof (ACPI_OBJECT_DATA)); 514 515 AcpiOsPrintf ("\n"); 516 517 AcpiOsPrintf ("ParseObject %3d\n", sizeof (ACPI_PARSE_OBJ_COMMON)); 518 AcpiOsPrintf ("ParseObjectNamed %3d\n", sizeof (ACPI_PARSE_OBJ_NAMED)); 519 AcpiOsPrintf ("ParseObjectAsl %3d\n", sizeof (ACPI_PARSE_OBJ_ASL)); 520 AcpiOsPrintf ("OperandObject %3d\n", sizeof (ACPI_OPERAND_OBJECT)); 521 AcpiOsPrintf ("NamespaceNode %3d\n", sizeof (ACPI_NAMESPACE_NODE)); 522 AcpiOsPrintf ("AcpiObject %3d\n", sizeof (ACPI_OBJECT)); 523 524 AcpiOsPrintf ("\n"); 525 526 AcpiOsPrintf ("Generic State %3d\n", sizeof (ACPI_GENERIC_STATE)); 527 AcpiOsPrintf ("Common State %3d\n", sizeof (ACPI_COMMON_STATE)); 528 AcpiOsPrintf ("Control State %3d\n", sizeof (ACPI_CONTROL_STATE)); 529 AcpiOsPrintf ("Update State %3d\n", sizeof (ACPI_UPDATE_STATE)); 530 AcpiOsPrintf ("Scope State %3d\n", sizeof (ACPI_SCOPE_STATE)); 531 AcpiOsPrintf ("Parse Scope %3d\n", sizeof (ACPI_PSCOPE_STATE)); 532 AcpiOsPrintf ("Package State %3d\n", sizeof (ACPI_PKG_STATE)); 533 AcpiOsPrintf ("Thread State %3d\n", sizeof (ACPI_THREAD_STATE)); 534 AcpiOsPrintf ("Result Values %3d\n", sizeof (ACPI_RESULT_VALUES)); 535 AcpiOsPrintf ("Notify Info %3d\n", sizeof (ACPI_NOTIFY_INFO)); 536 break; 537 538 case CMD_STAT_STACK: 539 #if defined(ACPI_DEBUG_OUTPUT) 540 541 Temp = (UINT32) ACPI_PTR_DIFF ( 542 AcpiGbl_EntryStackPointer, AcpiGbl_LowestStackPointer); 543 544 AcpiOsPrintf ("\nSubsystem Stack Usage:\n\n"); 545 AcpiOsPrintf ("Entry Stack Pointer %p\n", AcpiGbl_EntryStackPointer); 546 AcpiOsPrintf ("Lowest Stack Pointer %p\n", AcpiGbl_LowestStackPointer); 547 AcpiOsPrintf ("Stack Use %X (%u)\n", Temp, Temp); 548 AcpiOsPrintf ("Deepest Procedure Nesting %u\n", AcpiGbl_DeepestNesting); 549 #endif 550 break; 551 552 default: 553 554 break; 555 } 556 557 AcpiOsPrintf ("\n"); 558 return (AE_OK); 559 } 560 561 #endif /* ACPI_DEBUGGER */ 562