1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /*******************************************************************************
3  *
4  * Module Name: dbstats - Generation and display of ACPI table statistics
5  *
6  ******************************************************************************/
7 
8 #include <acpi/acpi.h>
9 #include "accommon.h"
10 #include "acdebug.h"
11 #include "acnamesp.h"
12 
13 #define _COMPONENT          ACPI_CA_DEBUGGER
14 ACPI_MODULE_NAME("dbstats")
15 
16 /* Local prototypes */
17 static void acpi_db_count_namespace_objects(void);
18 
19 static void acpi_db_enumerate_object(union acpi_operand_object *obj_desc);
20 
21 static acpi_status
22 acpi_db_classify_one_object(acpi_handle obj_handle,
23 			    u32 nesting_level,
24 			    void *context, void **return_value);
25 
26 #if defined ACPI_DBG_TRACK_ALLOCATIONS || defined ACPI_USE_LOCAL_CACHE
27 static void acpi_db_list_info(struct acpi_memory_list *list);
28 #endif
29 
30 /*
31  * Statistics subcommands
32  */
33 static struct acpi_db_argument_info acpi_db_stat_types[] = {
34 	{"ALLOCATIONS"},
35 	{"OBJECTS"},
36 	{"MEMORY"},
37 	{"MISC"},
38 	{"TABLES"},
39 	{"SIZES"},
40 	{"STACK"},
41 	{NULL}			/* Must be null terminated */
42 };
43 
44 #define CMD_STAT_ALLOCATIONS     0
45 #define CMD_STAT_OBJECTS         1
46 #define CMD_STAT_MEMORY          2
47 #define CMD_STAT_MISC            3
48 #define CMD_STAT_TABLES          4
49 #define CMD_STAT_SIZES           5
50 #define CMD_STAT_STACK           6
51 
52 #if defined ACPI_DBG_TRACK_ALLOCATIONS || defined ACPI_USE_LOCAL_CACHE
53 /*******************************************************************************
54  *
55  * FUNCTION:    acpi_db_list_info
56  *
57  * PARAMETERS:  list            - Memory list/cache to be displayed
58  *
59  * RETURN:      None
60  *
61  * DESCRIPTION: Display information about the input memory list or cache.
62  *
63  ******************************************************************************/
64 
acpi_db_list_info(struct acpi_memory_list * list)65 static void acpi_db_list_info(struct acpi_memory_list *list)
66 {
67 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
68 	u32 outstanding;
69 #endif
70 
71 	acpi_os_printf("\n%s\n", list->list_name);
72 
73 	/* max_depth > 0 indicates a cache object */
74 
75 	if (list->max_depth > 0) {
76 		acpi_os_printf
77 		    ("    Cache: [Depth    MaxD Avail  Size]                "
78 		     "%8.2X %8.2X %8.2X %8.2X\n", list->current_depth,
79 		     list->max_depth, list->max_depth - list->current_depth,
80 		     (list->current_depth * list->object_size));
81 	}
82 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
83 	if (list->max_depth > 0) {
84 		acpi_os_printf
85 		    ("    Cache: [Requests Hits Misses ObjSize]             "
86 		     "%8.2X %8.2X %8.2X %8.2X\n", list->requests, list->hits,
87 		     list->requests - list->hits, list->object_size);
88 	}
89 
90 	outstanding = acpi_db_get_cache_info(list);
91 
92 	if (list->object_size) {
93 		acpi_os_printf
94 		    ("    Mem:   [Alloc    Free Max    CurSize Outstanding] "
95 		     "%8.2X %8.2X %8.2X %8.2X %8.2X\n", list->total_allocated,
96 		     list->total_freed, list->max_occupied,
97 		     outstanding * list->object_size, outstanding);
98 	} else {
99 		acpi_os_printf
100 		    ("    Mem:   [Alloc Free Max CurSize Outstanding Total] "
101 		     "%8.2X %8.2X %8.2X %8.2X %8.2X %8.2X\n",
102 		     list->total_allocated, list->total_freed,
103 		     list->max_occupied, list->current_total_size, outstanding,
104 		     list->total_size);
105 	}
106 #endif
107 }
108 #endif
109 
110 /*******************************************************************************
111  *
112  * FUNCTION:    acpi_db_enumerate_object
113  *
114  * PARAMETERS:  obj_desc            - Object to be counted
115  *
116  * RETURN:      None
117  *
118  * DESCRIPTION: Add this object to the global counts, by object type.
119  *              Limited recursion handles subobjects and packages, and this
120  *              is probably acceptable within the AML debugger only.
121  *
122  ******************************************************************************/
123 
acpi_db_enumerate_object(union acpi_operand_object * obj_desc)124 static void acpi_db_enumerate_object(union acpi_operand_object *obj_desc)
125 {
126 	u32 i;
127 
128 	if (!obj_desc) {
129 		return;
130 	}
131 
132 	/* Enumerate this object first */
133 
134 	acpi_gbl_num_objects++;
135 
136 	if (obj_desc->common.type > ACPI_TYPE_NS_NODE_MAX) {
137 		acpi_gbl_obj_type_count_misc++;
138 	} else {
139 		acpi_gbl_obj_type_count[obj_desc->common.type]++;
140 	}
141 
142 	/* Count the sub-objects */
143 
144 	switch (obj_desc->common.type) {
145 	case ACPI_TYPE_PACKAGE:
146 
147 		for (i = 0; i < obj_desc->package.count; i++) {
148 			acpi_db_enumerate_object(obj_desc->package.elements[i]);
149 		}
150 		break;
151 
152 	case ACPI_TYPE_DEVICE:
153 
154 		acpi_db_enumerate_object(obj_desc->device.notify_list[0]);
155 		acpi_db_enumerate_object(obj_desc->device.notify_list[1]);
156 		acpi_db_enumerate_object(obj_desc->device.handler);
157 		break;
158 
159 	case ACPI_TYPE_BUFFER_FIELD:
160 
161 		if (acpi_ns_get_secondary_object(obj_desc)) {
162 			acpi_gbl_obj_type_count[ACPI_TYPE_BUFFER_FIELD]++;
163 		}
164 		break;
165 
166 	case ACPI_TYPE_REGION:
167 
168 		acpi_gbl_obj_type_count[ACPI_TYPE_LOCAL_REGION_FIELD]++;
169 		acpi_db_enumerate_object(obj_desc->region.handler);
170 		break;
171 
172 	case ACPI_TYPE_POWER:
173 
174 		acpi_db_enumerate_object(obj_desc->power_resource.
175 					 notify_list[0]);
176 		acpi_db_enumerate_object(obj_desc->power_resource.
177 					 notify_list[1]);
178 		break;
179 
180 	case ACPI_TYPE_PROCESSOR:
181 
182 		acpi_db_enumerate_object(obj_desc->processor.notify_list[0]);
183 		acpi_db_enumerate_object(obj_desc->processor.notify_list[1]);
184 		acpi_db_enumerate_object(obj_desc->processor.handler);
185 		break;
186 
187 	case ACPI_TYPE_THERMAL:
188 
189 		acpi_db_enumerate_object(obj_desc->thermal_zone.notify_list[0]);
190 		acpi_db_enumerate_object(obj_desc->thermal_zone.notify_list[1]);
191 		acpi_db_enumerate_object(obj_desc->thermal_zone.handler);
192 		break;
193 
194 	default:
195 
196 		break;
197 	}
198 }
199 
200 /*******************************************************************************
201  *
202  * FUNCTION:    acpi_db_classify_one_object
203  *
204  * PARAMETERS:  Callback for walk_namespace
205  *
206  * RETURN:      Status
207  *
208  * DESCRIPTION: Enumerate both the object descriptor (including subobjects) and
209  *              the parent namespace node.
210  *
211  ******************************************************************************/
212 
213 static acpi_status
acpi_db_classify_one_object(acpi_handle obj_handle,u32 nesting_level,void * context,void ** return_value)214 acpi_db_classify_one_object(acpi_handle obj_handle,
215 			    u32 nesting_level,
216 			    void *context, void **return_value)
217 {
218 	struct acpi_namespace_node *node;
219 	union acpi_operand_object *obj_desc;
220 	u32 type;
221 
222 	acpi_gbl_num_nodes++;
223 
224 	node = (struct acpi_namespace_node *)obj_handle;
225 	obj_desc = acpi_ns_get_attached_object(node);
226 
227 	acpi_db_enumerate_object(obj_desc);
228 
229 	type = node->type;
230 	if (type > ACPI_TYPE_NS_NODE_MAX) {
231 		acpi_gbl_node_type_count_misc++;
232 	} else {
233 		acpi_gbl_node_type_count[type]++;
234 	}
235 
236 	return (AE_OK);
237 
238 #ifdef ACPI_FUTURE_IMPLEMENTATION
239 
240 	/* TBD: These need to be counted during the initial parsing phase */
241 
242 	if (acpi_ps_is_named_op(op->opcode)) {
243 		num_nodes++;
244 	}
245 
246 	if (is_method) {
247 		num_method_elements++;
248 	}
249 
250 	num_grammar_elements++;
251 	op = acpi_ps_get_depth_next(root, op);
252 
253 	size_of_parse_tree = (num_grammar_elements - num_method_elements) *
254 	    (u32)sizeof(union acpi_parse_object);
255 	size_of_method_trees =
256 	    num_method_elements * (u32)sizeof(union acpi_parse_object);
257 	size_of_node_entries =
258 	    num_nodes * (u32)sizeof(struct acpi_namespace_node);
259 	size_of_acpi_objects =
260 	    num_nodes * (u32)sizeof(union acpi_operand_object);
261 #endif
262 }
263 
264 /*******************************************************************************
265  *
266  * FUNCTION:    acpi_db_count_namespace_objects
267  *
268  * PARAMETERS:  None
269  *
270  * RETURN:      None
271  *
272  * DESCRIPTION: Count and classify the entire namespace, including all
273  *              namespace nodes and attached objects.
274  *
275  ******************************************************************************/
276 
acpi_db_count_namespace_objects(void)277 static void acpi_db_count_namespace_objects(void)
278 {
279 	u32 i;
280 
281 	acpi_gbl_num_nodes = 0;
282 	acpi_gbl_num_objects = 0;
283 
284 	acpi_gbl_obj_type_count_misc = 0;
285 	for (i = 0; i < (ACPI_TYPE_NS_NODE_MAX - 1); i++) {
286 		acpi_gbl_obj_type_count[i] = 0;
287 		acpi_gbl_node_type_count[i] = 0;
288 	}
289 
290 	(void)acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
291 				     ACPI_UINT32_MAX, FALSE,
292 				     acpi_db_classify_one_object, NULL, NULL,
293 				     NULL);
294 }
295 
296 /*******************************************************************************
297  *
298  * FUNCTION:    acpi_db_display_statistics
299  *
300  * PARAMETERS:  type_arg        - Subcommand
301  *
302  * RETURN:      Status
303  *
304  * DESCRIPTION: Display various statistics
305  *
306  ******************************************************************************/
307 
acpi_db_display_statistics(char * type_arg)308 acpi_status acpi_db_display_statistics(char *type_arg)
309 {
310 	u32 i;
311 	u32 temp;
312 
313 	acpi_ut_strupr(type_arg);
314 	temp = acpi_db_match_argument(type_arg, acpi_db_stat_types);
315 	if (temp == ACPI_TYPE_NOT_FOUND) {
316 		acpi_os_printf("Invalid or unsupported argument\n");
317 		return (AE_OK);
318 	}
319 
320 	switch (temp) {
321 	case CMD_STAT_ALLOCATIONS:
322 
323 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
324 		acpi_ut_dump_allocation_info();
325 #endif
326 		break;
327 
328 	case CMD_STAT_TABLES:
329 
330 		acpi_os_printf("ACPI Table Information (not implemented):\n\n");
331 		break;
332 
333 	case CMD_STAT_OBJECTS:
334 
335 		acpi_db_count_namespace_objects();
336 
337 		acpi_os_printf
338 		    ("\nObjects defined in the current namespace:\n\n");
339 
340 		acpi_os_printf("%16.16s %10.10s %10.10s\n",
341 			       "ACPI_TYPE", "NODES", "OBJECTS");
342 
343 		for (i = 0; i < ACPI_TYPE_NS_NODE_MAX; i++) {
344 			acpi_os_printf("%16.16s %10u %10u\n",
345 				       acpi_ut_get_type_name(i),
346 				       acpi_gbl_node_type_count[i],
347 				       acpi_gbl_obj_type_count[i]);
348 		}
349 
350 		acpi_os_printf("%16.16s %10u %10u\n", "Misc/Unknown",
351 			       acpi_gbl_node_type_count_misc,
352 			       acpi_gbl_obj_type_count_misc);
353 
354 		acpi_os_printf("%16.16s %10u %10u\n", "TOTALS:",
355 			       acpi_gbl_num_nodes, acpi_gbl_num_objects);
356 		break;
357 
358 	case CMD_STAT_MEMORY:
359 
360 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
361 		acpi_os_printf
362 		    ("\n----Object Statistics (all in hex)---------\n");
363 
364 		acpi_db_list_info(acpi_gbl_global_list);
365 		acpi_db_list_info(acpi_gbl_ns_node_list);
366 #endif
367 
368 #ifdef ACPI_USE_LOCAL_CACHE
369 		acpi_os_printf
370 		    ("\n----Cache Statistics (all in hex)---------\n");
371 		acpi_db_list_info(acpi_gbl_operand_cache);
372 		acpi_db_list_info(acpi_gbl_ps_node_cache);
373 		acpi_db_list_info(acpi_gbl_ps_node_ext_cache);
374 		acpi_db_list_info(acpi_gbl_state_cache);
375 #endif
376 
377 		break;
378 
379 	case CMD_STAT_MISC:
380 
381 		acpi_os_printf("\nMiscellaneous Statistics:\n\n");
382 		acpi_os_printf("%-28s:     %7u\n", "Calls to AcpiPsFind",
383 			       acpi_gbl_ps_find_count);
384 		acpi_os_printf("%-28s:     %7u\n", "Calls to AcpiNsLookup",
385 			       acpi_gbl_ns_lookup_count);
386 
387 		acpi_os_printf("\nMutex usage:\n\n");
388 		for (i = 0; i < ACPI_NUM_MUTEX; i++) {
389 			acpi_os_printf("%-28s:     %7u\n",
390 				       acpi_ut_get_mutex_name(i),
391 				       acpi_gbl_mutex_info[i].use_count);
392 		}
393 		break;
394 
395 	case CMD_STAT_SIZES:
396 
397 		acpi_os_printf("\nInternal object sizes:\n\n");
398 
399 		acpi_os_printf("Common         %3d\n",
400 			       (u32)sizeof(struct acpi_object_common));
401 		acpi_os_printf("Number         %3d\n",
402 			       (u32)sizeof(struct acpi_object_integer));
403 		acpi_os_printf("String         %3d\n",
404 			       (u32)sizeof(struct acpi_object_string));
405 		acpi_os_printf("Buffer         %3d\n",
406 			       (u32)sizeof(struct acpi_object_buffer));
407 		acpi_os_printf("Package        %3d\n",
408 			       (u32)sizeof(struct acpi_object_package));
409 		acpi_os_printf("BufferField    %3d\n",
410 			       (u32)sizeof(struct acpi_object_buffer_field));
411 		acpi_os_printf("Device         %3d\n",
412 			       (u32)sizeof(struct acpi_object_device));
413 		acpi_os_printf("Event          %3d\n",
414 			       (u32)sizeof(struct acpi_object_event));
415 		acpi_os_printf("Method         %3d\n",
416 			       (u32)sizeof(struct acpi_object_method));
417 		acpi_os_printf("Mutex          %3d\n",
418 			       (u32)sizeof(struct acpi_object_mutex));
419 		acpi_os_printf("Region         %3d\n",
420 			       (u32)sizeof(struct acpi_object_region));
421 		acpi_os_printf("PowerResource  %3d\n",
422 			       (u32)sizeof(struct acpi_object_power_resource));
423 		acpi_os_printf("Processor      %3d\n",
424 			       (u32)sizeof(struct acpi_object_processor));
425 		acpi_os_printf("ThermalZone    %3d\n",
426 			       (u32)sizeof(struct acpi_object_thermal_zone));
427 		acpi_os_printf("RegionField    %3d\n",
428 			       (u32)sizeof(struct acpi_object_region_field));
429 		acpi_os_printf("BankField      %3d\n",
430 			       (u32)sizeof(struct acpi_object_bank_field));
431 		acpi_os_printf("IndexField     %3d\n",
432 			       (u32)sizeof(struct acpi_object_index_field));
433 		acpi_os_printf("Reference      %3d\n",
434 			       (u32)sizeof(struct acpi_object_reference));
435 		acpi_os_printf("Notify         %3d\n",
436 			       (u32)sizeof(struct acpi_object_notify_handler));
437 		acpi_os_printf("AddressSpace   %3d\n",
438 			       (u32)sizeof(struct acpi_object_addr_handler));
439 		acpi_os_printf("Extra          %3d\n",
440 			       (u32)sizeof(struct acpi_object_extra));
441 		acpi_os_printf("Data           %3d\n",
442 			       (u32)sizeof(struct acpi_object_data));
443 
444 		acpi_os_printf("\n");
445 
446 		acpi_os_printf("ParseObject    %3d\n",
447 			       (u32)sizeof(struct acpi_parse_obj_common));
448 		acpi_os_printf("ParseObjectNamed %3d\n",
449 			       (u32)sizeof(struct acpi_parse_obj_named));
450 		acpi_os_printf("ParseObjectAsl %3d\n",
451 			       (u32)sizeof(struct acpi_parse_obj_asl));
452 		acpi_os_printf("OperandObject  %3d\n",
453 			       (u32)sizeof(union acpi_operand_object));
454 		acpi_os_printf("NamespaceNode  %3d\n",
455 			       (u32)sizeof(struct acpi_namespace_node));
456 		acpi_os_printf("AcpiObject     %3d\n",
457 			       (u32)sizeof(union acpi_object));
458 
459 		acpi_os_printf("\n");
460 
461 		acpi_os_printf("Generic State  %3d\n",
462 			       (u32)sizeof(union acpi_generic_state));
463 		acpi_os_printf("Common State   %3d\n",
464 			       (u32)sizeof(struct acpi_common_state));
465 		acpi_os_printf("Control State  %3d\n",
466 			       (u32)sizeof(struct acpi_control_state));
467 		acpi_os_printf("Update State   %3d\n",
468 			       (u32)sizeof(struct acpi_update_state));
469 		acpi_os_printf("Scope State    %3d\n",
470 			       (u32)sizeof(struct acpi_scope_state));
471 		acpi_os_printf("Parse Scope    %3d\n",
472 			       (u32)sizeof(struct acpi_pscope_state));
473 		acpi_os_printf("Package State  %3d\n",
474 			       (u32)sizeof(struct acpi_pkg_state));
475 		acpi_os_printf("Thread State   %3d\n",
476 			       (u32)sizeof(struct acpi_thread_state));
477 		acpi_os_printf("Result Values  %3d\n",
478 			       (u32)sizeof(struct acpi_result_values));
479 		acpi_os_printf("Notify Info    %3d\n",
480 			       (u32)sizeof(struct acpi_notify_info));
481 		break;
482 
483 	case CMD_STAT_STACK:
484 #if defined(ACPI_DEBUG_OUTPUT)
485 
486 		temp =
487 		    (u32)ACPI_PTR_DIFF(acpi_gbl_entry_stack_pointer,
488 				       acpi_gbl_lowest_stack_pointer);
489 
490 		acpi_os_printf("\nSubsystem Stack Usage:\n\n");
491 		acpi_os_printf("Entry Stack Pointer        %p\n",
492 			       acpi_gbl_entry_stack_pointer);
493 		acpi_os_printf("Lowest Stack Pointer       %p\n",
494 			       acpi_gbl_lowest_stack_pointer);
495 		acpi_os_printf("Stack Use                  %X (%u)\n", temp,
496 			       temp);
497 		acpi_os_printf("Deepest Procedure Nesting  %u\n",
498 			       acpi_gbl_deepest_nesting);
499 #endif
500 		break;
501 
502 	default:
503 
504 		break;
505 	}
506 
507 	acpi_os_printf("\n");
508 	return (AE_OK);
509 }
510