1 /*******************************************************************************
2 *
3 * Module Name: dbstats - Generation and display of ACPI table statistics
4 *
5 ******************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2023, 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 MERCHANTABILITY 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
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
AcpiDbListInfo(ACPI_MEMORY_LIST * List)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
AcpiDbEnumerateObject(ACPI_OPERAND_OBJECT * ObjDesc)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
AcpiDbClassifyOneObject(ACPI_HANDLE ObjHandle,UINT32 NestingLevel,void * Context,void ** ReturnValue)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
AcpiDbCountNamespaceObjects(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
AcpiDbDisplayStatistics(char * TypeArg)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 %10u %10u\n", AcpiUtGetTypeName (i),
440 AcpiGbl_NodeTypeCount [i], AcpiGbl_ObjTypeCount [i]);
441 }
442
443 AcpiOsPrintf ("%16.16s %10u %10u\n", "Misc/Unknown",
444 AcpiGbl_NodeTypeCountMisc, AcpiGbl_ObjTypeCountMisc);
445
446 AcpiOsPrintf ("%16.16s %10u %10u\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 ("%-28s: %7u\n", "Calls to AcpiPsFind",
473 AcpiGbl_PsFindCount);
474 AcpiOsPrintf ("%-28s: %7u\n", "Calls to AcpiNsLookup",
475 AcpiGbl_NsLookupCount);
476
477 AcpiOsPrintf ("\nMutex usage:\n\n");
478 for (i = 0; i < ACPI_NUM_MUTEX; i++)
479 {
480 AcpiOsPrintf ("%-28s: %7u\n",
481 AcpiUtGetMutexName (i), AcpiGbl_MutexInfo[i].UseCount);
482 }
483 break;
484
485 case CMD_STAT_SIZES:
486
487 AcpiOsPrintf ("\nInternal object sizes:\n\n");
488
489 AcpiOsPrintf ("Common %3d\n", (UINT32) sizeof (ACPI_OBJECT_COMMON));
490 AcpiOsPrintf ("Number %3d\n", (UINT32) sizeof (ACPI_OBJECT_INTEGER));
491 AcpiOsPrintf ("String %3d\n", (UINT32) sizeof (ACPI_OBJECT_STRING));
492 AcpiOsPrintf ("Buffer %3d\n", (UINT32) sizeof (ACPI_OBJECT_BUFFER));
493 AcpiOsPrintf ("Package %3d\n", (UINT32) sizeof (ACPI_OBJECT_PACKAGE));
494 AcpiOsPrintf ("BufferField %3d\n", (UINT32) sizeof (ACPI_OBJECT_BUFFER_FIELD));
495 AcpiOsPrintf ("Device %3d\n", (UINT32) sizeof (ACPI_OBJECT_DEVICE));
496 AcpiOsPrintf ("Event %3d\n", (UINT32) sizeof (ACPI_OBJECT_EVENT));
497 AcpiOsPrintf ("Method %3d\n", (UINT32) sizeof (ACPI_OBJECT_METHOD));
498 AcpiOsPrintf ("Mutex %3d\n", (UINT32) sizeof (ACPI_OBJECT_MUTEX));
499 AcpiOsPrintf ("Region %3d\n", (UINT32) sizeof (ACPI_OBJECT_REGION));
500 AcpiOsPrintf ("PowerResource %3d\n", (UINT32) sizeof (ACPI_OBJECT_POWER_RESOURCE));
501 AcpiOsPrintf ("Processor %3d\n", (UINT32) sizeof (ACPI_OBJECT_PROCESSOR));
502 AcpiOsPrintf ("ThermalZone %3d\n", (UINT32) sizeof (ACPI_OBJECT_THERMAL_ZONE));
503 AcpiOsPrintf ("RegionField %3d\n", (UINT32) sizeof (ACPI_OBJECT_REGION_FIELD));
504 AcpiOsPrintf ("BankField %3d\n", (UINT32) sizeof (ACPI_OBJECT_BANK_FIELD));
505 AcpiOsPrintf ("IndexField %3d\n", (UINT32) sizeof (ACPI_OBJECT_INDEX_FIELD));
506 AcpiOsPrintf ("Reference %3d\n", (UINT32) sizeof (ACPI_OBJECT_REFERENCE));
507 AcpiOsPrintf ("Notify %3d\n", (UINT32) sizeof (ACPI_OBJECT_NOTIFY_HANDLER));
508 AcpiOsPrintf ("AddressSpace %3d\n", (UINT32) sizeof (ACPI_OBJECT_ADDR_HANDLER));
509 AcpiOsPrintf ("Extra %3d\n", (UINT32) sizeof (ACPI_OBJECT_EXTRA));
510 AcpiOsPrintf ("Data %3d\n", (UINT32) sizeof (ACPI_OBJECT_DATA));
511
512 AcpiOsPrintf ("\n");
513
514 AcpiOsPrintf ("ParseObject %3d\n", (UINT32) sizeof (ACPI_PARSE_OBJ_COMMON));
515 AcpiOsPrintf ("ParseObjectNamed %3d\n", (UINT32) sizeof (ACPI_PARSE_OBJ_NAMED));
516 AcpiOsPrintf ("ParseObjectAsl %3d\n", (UINT32) sizeof (ACPI_PARSE_OBJ_ASL));
517 AcpiOsPrintf ("OperandObject %3d\n", (UINT32) sizeof (ACPI_OPERAND_OBJECT));
518 AcpiOsPrintf ("NamespaceNode %3d\n", (UINT32) sizeof (ACPI_NAMESPACE_NODE));
519 AcpiOsPrintf ("AcpiObject %3d\n", (UINT32) sizeof (ACPI_OBJECT));
520
521 AcpiOsPrintf ("\n");
522
523 AcpiOsPrintf ("Generic State %3d\n", (UINT32) sizeof (ACPI_GENERIC_STATE));
524 AcpiOsPrintf ("Common State %3d\n", (UINT32) sizeof (ACPI_COMMON_STATE));
525 AcpiOsPrintf ("Control State %3d\n", (UINT32) sizeof (ACPI_CONTROL_STATE));
526 AcpiOsPrintf ("Update State %3d\n", (UINT32) sizeof (ACPI_UPDATE_STATE));
527 AcpiOsPrintf ("Scope State %3d\n", (UINT32) sizeof (ACPI_SCOPE_STATE));
528 AcpiOsPrintf ("Parse Scope %3d\n", (UINT32) sizeof (ACPI_PSCOPE_STATE));
529 AcpiOsPrintf ("Package State %3d\n", (UINT32) sizeof (ACPI_PKG_STATE));
530 AcpiOsPrintf ("Thread State %3d\n", (UINT32) sizeof (ACPI_THREAD_STATE));
531 AcpiOsPrintf ("Result Values %3d\n", (UINT32) sizeof (ACPI_RESULT_VALUES));
532 AcpiOsPrintf ("Notify Info %3d\n", (UINT32) sizeof (ACPI_NOTIFY_INFO));
533 break;
534
535 case CMD_STAT_STACK:
536 #if defined(ACPI_DEBUG_OUTPUT)
537
538 Temp = (UINT32) ACPI_PTR_DIFF (
539 AcpiGbl_EntryStackPointer, AcpiGbl_LowestStackPointer);
540
541 AcpiOsPrintf ("\nSubsystem Stack Usage:\n\n");
542 AcpiOsPrintf ("Entry Stack Pointer %p\n", AcpiGbl_EntryStackPointer);
543 AcpiOsPrintf ("Lowest Stack Pointer %p\n", AcpiGbl_LowestStackPointer);
544 AcpiOsPrintf ("Stack Use %X (%u)\n", Temp, Temp);
545 AcpiOsPrintf ("Deepest Procedure Nesting %u\n", AcpiGbl_DeepestNesting);
546 #endif
547 break;
548
549 default:
550
551 break;
552 }
553
554 AcpiOsPrintf ("\n");
555 return (AE_OK);
556 }
557