xref: /freebsd/sys/contrib/dev/acpica/components/debugger/dbstats.c (revision 39ee7a7a6bdd1557b1c3532abf60d139798ac88b)
1 /*******************************************************************************
2  *
3  * Module Name: dbstats - Generation and display of ACPI table statistics
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, 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         AcpiOsPrintf ("%16.16s % 10ld% 10ld\n", "Misc/Unknown",
443             AcpiGbl_NodeTypeCountMisc, AcpiGbl_ObjTypeCountMisc);
444 
445         AcpiOsPrintf ("%16.16s % 10ld% 10ld\n", "TOTALS:",
446             AcpiGbl_NumNodes, AcpiGbl_NumObjects);
447         break;
448 
449     case CMD_STAT_MEMORY:
450 
451 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
452         AcpiOsPrintf ("\n----Object Statistics (all in hex)---------\n");
453 
454         AcpiDbListInfo (AcpiGbl_GlobalList);
455         AcpiDbListInfo (AcpiGbl_NsNodeList);
456 #endif
457 
458 #ifdef ACPI_USE_LOCAL_CACHE
459         AcpiOsPrintf ("\n----Cache Statistics (all in hex)---------\n");
460         AcpiDbListInfo (AcpiGbl_OperandCache);
461         AcpiDbListInfo (AcpiGbl_PsNodeCache);
462         AcpiDbListInfo (AcpiGbl_PsNodeExtCache);
463         AcpiDbListInfo (AcpiGbl_StateCache);
464 #endif
465 
466         break;
467 
468     case CMD_STAT_MISC:
469 
470         AcpiOsPrintf ("\nMiscellaneous Statistics:\n\n");
471         AcpiOsPrintf ("Calls to AcpiPsFind:..  ........% 7ld\n",
472             AcpiGbl_PsFindCount);
473         AcpiOsPrintf ("Calls to AcpiNsLookup:..........% 7ld\n",
474             AcpiGbl_NsLookupCount);
475 
476         AcpiOsPrintf ("\n");
477 
478         AcpiOsPrintf ("Mutex usage:\n\n");
479         for (i = 0; i < ACPI_NUM_MUTEX; i++)
480         {
481             AcpiOsPrintf ("%-28s:       % 7ld\n",
482                 AcpiUtGetMutexName (i), AcpiGbl_MutexInfo[i].UseCount);
483         }
484         break;
485 
486     case CMD_STAT_SIZES:
487 
488         AcpiOsPrintf ("\nInternal object sizes:\n\n");
489 
490         AcpiOsPrintf ("Common           %3d\n", sizeof (ACPI_OBJECT_COMMON));
491         AcpiOsPrintf ("Number           %3d\n", sizeof (ACPI_OBJECT_INTEGER));
492         AcpiOsPrintf ("String           %3d\n", sizeof (ACPI_OBJECT_STRING));
493         AcpiOsPrintf ("Buffer           %3d\n", sizeof (ACPI_OBJECT_BUFFER));
494         AcpiOsPrintf ("Package          %3d\n", sizeof (ACPI_OBJECT_PACKAGE));
495         AcpiOsPrintf ("BufferField      %3d\n", sizeof (ACPI_OBJECT_BUFFER_FIELD));
496         AcpiOsPrintf ("Device           %3d\n", sizeof (ACPI_OBJECT_DEVICE));
497         AcpiOsPrintf ("Event            %3d\n", sizeof (ACPI_OBJECT_EVENT));
498         AcpiOsPrintf ("Method           %3d\n", sizeof (ACPI_OBJECT_METHOD));
499         AcpiOsPrintf ("Mutex            %3d\n", sizeof (ACPI_OBJECT_MUTEX));
500         AcpiOsPrintf ("Region           %3d\n", sizeof (ACPI_OBJECT_REGION));
501         AcpiOsPrintf ("PowerResource    %3d\n", sizeof (ACPI_OBJECT_POWER_RESOURCE));
502         AcpiOsPrintf ("Processor        %3d\n", sizeof (ACPI_OBJECT_PROCESSOR));
503         AcpiOsPrintf ("ThermalZone      %3d\n", sizeof (ACPI_OBJECT_THERMAL_ZONE));
504         AcpiOsPrintf ("RegionField      %3d\n", sizeof (ACPI_OBJECT_REGION_FIELD));
505         AcpiOsPrintf ("BankField        %3d\n", sizeof (ACPI_OBJECT_BANK_FIELD));
506         AcpiOsPrintf ("IndexField       %3d\n", sizeof (ACPI_OBJECT_INDEX_FIELD));
507         AcpiOsPrintf ("Reference        %3d\n", sizeof (ACPI_OBJECT_REFERENCE));
508         AcpiOsPrintf ("Notify           %3d\n", sizeof (ACPI_OBJECT_NOTIFY_HANDLER));
509         AcpiOsPrintf ("AddressSpace     %3d\n", sizeof (ACPI_OBJECT_ADDR_HANDLER));
510         AcpiOsPrintf ("Extra            %3d\n", sizeof (ACPI_OBJECT_EXTRA));
511         AcpiOsPrintf ("Data             %3d\n", sizeof (ACPI_OBJECT_DATA));
512 
513         AcpiOsPrintf ("\n");
514 
515         AcpiOsPrintf ("ParseObject      %3d\n", sizeof (ACPI_PARSE_OBJ_COMMON));
516         AcpiOsPrintf ("ParseObjectNamed %3d\n", sizeof (ACPI_PARSE_OBJ_NAMED));
517         AcpiOsPrintf ("ParseObjectAsl   %3d\n", sizeof (ACPI_PARSE_OBJ_ASL));
518         AcpiOsPrintf ("OperandObject    %3d\n", sizeof (ACPI_OPERAND_OBJECT));
519         AcpiOsPrintf ("NamespaceNode    %3d\n", sizeof (ACPI_NAMESPACE_NODE));
520         AcpiOsPrintf ("AcpiObject       %3d\n", sizeof (ACPI_OBJECT));
521 
522         AcpiOsPrintf ("\n");
523 
524         AcpiOsPrintf ("Generic State    %3d\n", sizeof (ACPI_GENERIC_STATE));
525         AcpiOsPrintf ("Common State     %3d\n", sizeof (ACPI_COMMON_STATE));
526         AcpiOsPrintf ("Control State    %3d\n", sizeof (ACPI_CONTROL_STATE));
527         AcpiOsPrintf ("Update State     %3d\n", sizeof (ACPI_UPDATE_STATE));
528         AcpiOsPrintf ("Scope State      %3d\n", sizeof (ACPI_SCOPE_STATE));
529         AcpiOsPrintf ("Parse Scope      %3d\n", sizeof (ACPI_PSCOPE_STATE));
530         AcpiOsPrintf ("Package State    %3d\n", sizeof (ACPI_PKG_STATE));
531         AcpiOsPrintf ("Thread State     %3d\n", sizeof (ACPI_THREAD_STATE));
532         AcpiOsPrintf ("Result Values    %3d\n", sizeof (ACPI_RESULT_VALUES));
533         AcpiOsPrintf ("Notify Info      %3d\n", sizeof (ACPI_NOTIFY_INFO));
534         break;
535 
536     case CMD_STAT_STACK:
537 #if defined(ACPI_DEBUG_OUTPUT)
538 
539         Temp = (UINT32) ACPI_PTR_DIFF (
540             AcpiGbl_EntryStackPointer, AcpiGbl_LowestStackPointer);
541 
542         AcpiOsPrintf ("\nSubsystem Stack Usage:\n\n");
543         AcpiOsPrintf ("Entry Stack Pointer          %p\n", AcpiGbl_EntryStackPointer);
544         AcpiOsPrintf ("Lowest Stack Pointer         %p\n", AcpiGbl_LowestStackPointer);
545         AcpiOsPrintf ("Stack Use                    %X (%u)\n", Temp, Temp);
546         AcpiOsPrintf ("Deepest Procedure Nesting    %u\n", AcpiGbl_DeepestNesting);
547 #endif
548         break;
549 
550     default:
551 
552         break;
553     }
554 
555     AcpiOsPrintf ("\n");
556     return (AE_OK);
557 }
558