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 #include <contrib/dev/acpica/include/acpi.h> 45 #include <contrib/dev/acpica/include/accommon.h> 46 #include <contrib/dev/acpica/include/acdebug.h> 47 #include <contrib/dev/acpica/include/acnamesp.h> 48 49 #ifdef ACPI_DEBUGGER 50 51 #define _COMPONENT ACPI_CA_DEBUGGER 52 ACPI_MODULE_NAME ("dbstats") 53 54 /* Local prototypes */ 55 56 static void 57 AcpiDbCountNamespaceObjects ( 58 void); 59 60 static void 61 AcpiDbEnumerateObject ( 62 ACPI_OPERAND_OBJECT *ObjDesc); 63 64 static ACPI_STATUS 65 AcpiDbClassifyOneObject ( 66 ACPI_HANDLE ObjHandle, 67 UINT32 NestingLevel, 68 void *Context, 69 void **ReturnValue); 70 71 #if defined ACPI_DBG_TRACK_ALLOCATIONS || defined ACPI_USE_LOCAL_CACHE 72 static void 73 AcpiDbListInfo ( 74 ACPI_MEMORY_LIST *List); 75 #endif 76 77 78 /* 79 * Statistics subcommands 80 */ 81 static ACPI_DB_ARGUMENT_INFO AcpiDbStatTypes [] = 82 { 83 {"ALLOCATIONS"}, 84 {"OBJECTS"}, 85 {"MEMORY"}, 86 {"MISC"}, 87 {"TABLES"}, 88 {"SIZES"}, 89 {"STACK"}, 90 {NULL} /* Must be null terminated */ 91 }; 92 93 #define CMD_STAT_ALLOCATIONS 0 94 #define CMD_STAT_OBJECTS 1 95 #define CMD_STAT_MEMORY 2 96 #define CMD_STAT_MISC 3 97 #define CMD_STAT_TABLES 4 98 #define CMD_STAT_SIZES 5 99 #define CMD_STAT_STACK 6 100 101 102 #if defined ACPI_DBG_TRACK_ALLOCATIONS || defined ACPI_USE_LOCAL_CACHE 103 /******************************************************************************* 104 * 105 * FUNCTION: AcpiDbListInfo 106 * 107 * PARAMETERS: List - Memory list/cache to be displayed 108 * 109 * RETURN: None 110 * 111 * DESCRIPTION: Display information about the input memory list or cache. 112 * 113 ******************************************************************************/ 114 115 static void 116 AcpiDbListInfo ( 117 ACPI_MEMORY_LIST *List) 118 { 119 #ifdef ACPI_DBG_TRACK_ALLOCATIONS 120 UINT32 Outstanding; 121 #endif 122 123 AcpiOsPrintf ("\n%s\n", List->ListName); 124 125 /* MaxDepth > 0 indicates a cache object */ 126 127 if (List->MaxDepth > 0) 128 { 129 AcpiOsPrintf ( 130 " Cache: [Depth MaxD Avail Size] %8.2X %8.2X %8.2X %8.2X\n", 131 List->CurrentDepth, 132 List->MaxDepth, 133 List->MaxDepth - List->CurrentDepth, 134 (List->CurrentDepth * List->ObjectSize)); 135 } 136 137 #ifdef ACPI_DBG_TRACK_ALLOCATIONS 138 if (List->MaxDepth > 0) 139 { 140 AcpiOsPrintf ( 141 " Cache: [Requests Hits Misses ObjSize] %8.2X %8.2X %8.2X %8.2X\n", 142 List->Requests, 143 List->Hits, 144 List->Requests - List->Hits, 145 List->ObjectSize); 146 } 147 148 Outstanding = AcpiDbGetCacheInfo (List); 149 150 if (List->ObjectSize) 151 { 152 AcpiOsPrintf ( 153 " Mem: [Alloc Free Max CurSize Outstanding] %8.2X %8.2X %8.2X %8.2X %8.2X\n", 154 List->TotalAllocated, 155 List->TotalFreed, 156 List->MaxOccupied, 157 Outstanding * List->ObjectSize, 158 Outstanding); 159 } 160 else 161 { 162 AcpiOsPrintf ( 163 " Mem: [Alloc Free Max CurSize Outstanding Total] %8.2X %8.2X %8.2X %8.2X %8.2X %8.2X\n", 164 List->TotalAllocated, 165 List->TotalFreed, 166 List->MaxOccupied, 167 List->CurrentTotalSize, 168 Outstanding, 169 List->TotalSize); 170 } 171 #endif 172 } 173 #endif 174 175 176 /******************************************************************************* 177 * 178 * FUNCTION: AcpiDbEnumerateObject 179 * 180 * PARAMETERS: ObjDesc - Object to be counted 181 * 182 * RETURN: None 183 * 184 * DESCRIPTION: Add this object to the global counts, by object type. 185 * Limited recursion handles subobjects and packages, and this 186 * is probably acceptable within the AML debugger only. 187 * 188 ******************************************************************************/ 189 190 static void 191 AcpiDbEnumerateObject ( 192 ACPI_OPERAND_OBJECT *ObjDesc) 193 { 194 UINT32 i; 195 196 197 if (!ObjDesc) 198 { 199 return; 200 } 201 202 /* Enumerate this object first */ 203 204 AcpiGbl_NumObjects++; 205 206 if (ObjDesc->Common.Type > ACPI_TYPE_NS_NODE_MAX) 207 { 208 AcpiGbl_ObjTypeCountMisc++; 209 } 210 else 211 { 212 AcpiGbl_ObjTypeCount [ObjDesc->Common.Type]++; 213 } 214 215 /* Count the sub-objects */ 216 217 switch (ObjDesc->Common.Type) 218 { 219 case ACPI_TYPE_PACKAGE: 220 221 for (i = 0; i < ObjDesc->Package.Count; i++) 222 { 223 AcpiDbEnumerateObject (ObjDesc->Package.Elements[i]); 224 } 225 break; 226 227 case ACPI_TYPE_DEVICE: 228 229 AcpiDbEnumerateObject (ObjDesc->Device.NotifyList[0]); 230 AcpiDbEnumerateObject (ObjDesc->Device.NotifyList[1]); 231 AcpiDbEnumerateObject (ObjDesc->Device.Handler); 232 break; 233 234 case ACPI_TYPE_BUFFER_FIELD: 235 236 if (AcpiNsGetSecondaryObject (ObjDesc)) 237 { 238 AcpiGbl_ObjTypeCount [ACPI_TYPE_BUFFER_FIELD]++; 239 } 240 break; 241 242 case ACPI_TYPE_REGION: 243 244 AcpiGbl_ObjTypeCount [ACPI_TYPE_LOCAL_REGION_FIELD ]++; 245 AcpiDbEnumerateObject (ObjDesc->Region.Handler); 246 break; 247 248 case ACPI_TYPE_POWER: 249 250 AcpiDbEnumerateObject (ObjDesc->PowerResource.NotifyList[0]); 251 AcpiDbEnumerateObject (ObjDesc->PowerResource.NotifyList[1]); 252 break; 253 254 case ACPI_TYPE_PROCESSOR: 255 256 AcpiDbEnumerateObject (ObjDesc->Processor.NotifyList[0]); 257 AcpiDbEnumerateObject (ObjDesc->Processor.NotifyList[1]); 258 AcpiDbEnumerateObject (ObjDesc->Processor.Handler); 259 break; 260 261 case ACPI_TYPE_THERMAL: 262 263 AcpiDbEnumerateObject (ObjDesc->ThermalZone.NotifyList[0]); 264 AcpiDbEnumerateObject (ObjDesc->ThermalZone.NotifyList[1]); 265 AcpiDbEnumerateObject (ObjDesc->ThermalZone.Handler); 266 break; 267 268 default: 269 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 AcpiUtStrupr (TypeArg); 402 Temp = AcpiDbMatchArgument (TypeArg, AcpiDbStatTypes); 403 if (Temp == ACPI_TYPE_NOT_FOUND) 404 { 405 AcpiOsPrintf ("Invalid or unsupported argument\n"); 406 return (AE_OK); 407 } 408 409 410 switch (Temp) 411 { 412 case CMD_STAT_ALLOCATIONS: 413 414 #ifdef ACPI_DBG_TRACK_ALLOCATIONS 415 AcpiUtDumpAllocationInfo (); 416 #endif 417 break; 418 419 case CMD_STAT_TABLES: 420 421 AcpiOsPrintf ("ACPI Table Information (not implemented):\n\n"); 422 break; 423 424 case CMD_STAT_OBJECTS: 425 426 AcpiDbCountNamespaceObjects (); 427 428 AcpiOsPrintf ("\nObjects defined in the current namespace:\n\n"); 429 430 AcpiOsPrintf ("%16.16s %10.10s %10.10s\n", 431 "ACPI_TYPE", "NODES", "OBJECTS"); 432 433 for (i = 0; i < ACPI_TYPE_NS_NODE_MAX; i++) 434 { 435 AcpiOsPrintf ("%16.16s % 10ld% 10ld\n", AcpiUtGetTypeName (i), 436 AcpiGbl_NodeTypeCount [i], AcpiGbl_ObjTypeCount [i]); 437 } 438 AcpiOsPrintf ("%16.16s % 10ld% 10ld\n", "Misc/Unknown", 439 AcpiGbl_NodeTypeCountMisc, AcpiGbl_ObjTypeCountMisc); 440 441 AcpiOsPrintf ("%16.16s % 10ld% 10ld\n", "TOTALS:", 442 AcpiGbl_NumNodes, AcpiGbl_NumObjects); 443 break; 444 445 case CMD_STAT_MEMORY: 446 447 #ifdef ACPI_DBG_TRACK_ALLOCATIONS 448 AcpiOsPrintf ("\n----Object Statistics (all in hex)---------\n"); 449 450 AcpiDbListInfo (AcpiGbl_GlobalList); 451 AcpiDbListInfo (AcpiGbl_NsNodeList); 452 #endif 453 454 #ifdef ACPI_USE_LOCAL_CACHE 455 AcpiOsPrintf ("\n----Cache Statistics (all in hex)---------\n"); 456 AcpiDbListInfo (AcpiGbl_OperandCache); 457 AcpiDbListInfo (AcpiGbl_PsNodeCache); 458 AcpiDbListInfo (AcpiGbl_PsNodeExtCache); 459 AcpiDbListInfo (AcpiGbl_StateCache); 460 #endif 461 462 break; 463 464 case CMD_STAT_MISC: 465 466 AcpiOsPrintf ("\nMiscellaneous Statistics:\n\n"); 467 AcpiOsPrintf ("Calls to AcpiPsFind:.. ........% 7ld\n", 468 AcpiGbl_PsFindCount); 469 AcpiOsPrintf ("Calls to AcpiNsLookup:..........% 7ld\n", 470 AcpiGbl_NsLookupCount); 471 472 AcpiOsPrintf ("\n"); 473 474 AcpiOsPrintf ("Mutex usage:\n\n"); 475 for (i = 0; i < ACPI_NUM_MUTEX; i++) 476 { 477 AcpiOsPrintf ("%-28s: % 7ld\n", 478 AcpiUtGetMutexName (i), AcpiGbl_MutexInfo[i].UseCount); 479 } 480 break; 481 482 case CMD_STAT_SIZES: 483 484 AcpiOsPrintf ("\nInternal object sizes:\n\n"); 485 486 AcpiOsPrintf ("Common %3d\n", sizeof (ACPI_OBJECT_COMMON)); 487 AcpiOsPrintf ("Number %3d\n", sizeof (ACPI_OBJECT_INTEGER)); 488 AcpiOsPrintf ("String %3d\n", sizeof (ACPI_OBJECT_STRING)); 489 AcpiOsPrintf ("Buffer %3d\n", sizeof (ACPI_OBJECT_BUFFER)); 490 AcpiOsPrintf ("Package %3d\n", sizeof (ACPI_OBJECT_PACKAGE)); 491 AcpiOsPrintf ("BufferField %3d\n", sizeof (ACPI_OBJECT_BUFFER_FIELD)); 492 AcpiOsPrintf ("Device %3d\n", sizeof (ACPI_OBJECT_DEVICE)); 493 AcpiOsPrintf ("Event %3d\n", sizeof (ACPI_OBJECT_EVENT)); 494 AcpiOsPrintf ("Method %3d\n", sizeof (ACPI_OBJECT_METHOD)); 495 AcpiOsPrintf ("Mutex %3d\n", sizeof (ACPI_OBJECT_MUTEX)); 496 AcpiOsPrintf ("Region %3d\n", sizeof (ACPI_OBJECT_REGION)); 497 AcpiOsPrintf ("PowerResource %3d\n", sizeof (ACPI_OBJECT_POWER_RESOURCE)); 498 AcpiOsPrintf ("Processor %3d\n", sizeof (ACPI_OBJECT_PROCESSOR)); 499 AcpiOsPrintf ("ThermalZone %3d\n", sizeof (ACPI_OBJECT_THERMAL_ZONE)); 500 AcpiOsPrintf ("RegionField %3d\n", sizeof (ACPI_OBJECT_REGION_FIELD)); 501 AcpiOsPrintf ("BankField %3d\n", sizeof (ACPI_OBJECT_BANK_FIELD)); 502 AcpiOsPrintf ("IndexField %3d\n", sizeof (ACPI_OBJECT_INDEX_FIELD)); 503 AcpiOsPrintf ("Reference %3d\n", sizeof (ACPI_OBJECT_REFERENCE)); 504 AcpiOsPrintf ("Notify %3d\n", sizeof (ACPI_OBJECT_NOTIFY_HANDLER)); 505 AcpiOsPrintf ("AddressSpace %3d\n", sizeof (ACPI_OBJECT_ADDR_HANDLER)); 506 AcpiOsPrintf ("Extra %3d\n", sizeof (ACPI_OBJECT_EXTRA)); 507 AcpiOsPrintf ("Data %3d\n", sizeof (ACPI_OBJECT_DATA)); 508 509 AcpiOsPrintf ("\n"); 510 511 AcpiOsPrintf ("ParseObject %3d\n", sizeof (ACPI_PARSE_OBJ_COMMON)); 512 AcpiOsPrintf ("ParseObjectNamed %3d\n", sizeof (ACPI_PARSE_OBJ_NAMED)); 513 AcpiOsPrintf ("ParseObjectAsl %3d\n", sizeof (ACPI_PARSE_OBJ_ASL)); 514 AcpiOsPrintf ("OperandObject %3d\n", sizeof (ACPI_OPERAND_OBJECT)); 515 AcpiOsPrintf ("NamespaceNode %3d\n", sizeof (ACPI_NAMESPACE_NODE)); 516 AcpiOsPrintf ("AcpiObject %3d\n", sizeof (ACPI_OBJECT)); 517 518 AcpiOsPrintf ("\n"); 519 520 AcpiOsPrintf ("Generic State %3d\n", sizeof (ACPI_GENERIC_STATE)); 521 AcpiOsPrintf ("Common State %3d\n", sizeof (ACPI_COMMON_STATE)); 522 AcpiOsPrintf ("Control State %3d\n", sizeof (ACPI_CONTROL_STATE)); 523 AcpiOsPrintf ("Update State %3d\n", sizeof (ACPI_UPDATE_STATE)); 524 AcpiOsPrintf ("Scope State %3d\n", sizeof (ACPI_SCOPE_STATE)); 525 AcpiOsPrintf ("Parse Scope %3d\n", sizeof (ACPI_PSCOPE_STATE)); 526 AcpiOsPrintf ("Package State %3d\n", sizeof (ACPI_PKG_STATE)); 527 AcpiOsPrintf ("Thread State %3d\n", sizeof (ACPI_THREAD_STATE)); 528 AcpiOsPrintf ("Result Values %3d\n", sizeof (ACPI_RESULT_VALUES)); 529 AcpiOsPrintf ("Notify Info %3d\n", sizeof (ACPI_NOTIFY_INFO)); 530 break; 531 532 case CMD_STAT_STACK: 533 #if defined(ACPI_DEBUG_OUTPUT) 534 535 Temp = (UINT32) ACPI_PTR_DIFF (AcpiGbl_EntryStackPointer, AcpiGbl_LowestStackPointer); 536 537 AcpiOsPrintf ("\nSubsystem Stack Usage:\n\n"); 538 AcpiOsPrintf ("Entry Stack Pointer %p\n", AcpiGbl_EntryStackPointer); 539 AcpiOsPrintf ("Lowest Stack Pointer %p\n", AcpiGbl_LowestStackPointer); 540 AcpiOsPrintf ("Stack Use %X (%u)\n", Temp, Temp); 541 AcpiOsPrintf ("Deepest Procedure Nesting %u\n", AcpiGbl_DeepestNesting); 542 #endif 543 break; 544 545 default: 546 547 break; 548 } 549 550 AcpiOsPrintf ("\n"); 551 return (AE_OK); 552 } 553 554 #endif /* ACPI_DEBUGGER */ 555