1 /******************************************************************************* 2 * 3 * Module Name: dbstats - Generation and display of ACPI table statistics 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2013, 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 == (UINT32) -1) 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 */