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