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