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