xref: /OK3568_Linux_fs/kernel/drivers/acpi/acpica/dsdebug.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /******************************************************************************
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Module Name: dsdebug - Parser/Interpreter interface - debugging
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Copyright (C) 2000 - 2020, Intel Corp.
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  *****************************************************************************/
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <acpi/acpi.h>
11*4882a593Smuzhiyun #include "accommon.h"
12*4882a593Smuzhiyun #include "acdispat.h"
13*4882a593Smuzhiyun #include "acnamesp.h"
14*4882a593Smuzhiyun #ifdef ACPI_DISASSEMBLER
15*4882a593Smuzhiyun #include "acdisasm.h"
16*4882a593Smuzhiyun #endif
17*4882a593Smuzhiyun #include "acinterp.h"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #define _COMPONENT          ACPI_DISPATCHER
20*4882a593Smuzhiyun ACPI_MODULE_NAME("dsdebug")
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
23*4882a593Smuzhiyun /* Local prototypes */
24*4882a593Smuzhiyun static void
25*4882a593Smuzhiyun acpi_ds_print_node_pathname(struct acpi_namespace_node *node,
26*4882a593Smuzhiyun 			    const char *message);
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun /*******************************************************************************
29*4882a593Smuzhiyun  *
30*4882a593Smuzhiyun  * FUNCTION:    acpi_ds_print_node_pathname
31*4882a593Smuzhiyun  *
32*4882a593Smuzhiyun  * PARAMETERS:  node            - Object
33*4882a593Smuzhiyun  *              message         - Prefix message
34*4882a593Smuzhiyun  *
35*4882a593Smuzhiyun  * DESCRIPTION: Print an object's full namespace pathname
36*4882a593Smuzhiyun  *              Manages allocation/freeing of a pathname buffer
37*4882a593Smuzhiyun  *
38*4882a593Smuzhiyun  ******************************************************************************/
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun static void
acpi_ds_print_node_pathname(struct acpi_namespace_node * node,const char * message)41*4882a593Smuzhiyun acpi_ds_print_node_pathname(struct acpi_namespace_node *node,
42*4882a593Smuzhiyun 			    const char *message)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun 	struct acpi_buffer buffer;
45*4882a593Smuzhiyun 	acpi_status status;
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ds_print_node_pathname);
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	if (!node) {
50*4882a593Smuzhiyun 		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "[NULL NAME]"));
51*4882a593Smuzhiyun 		return_VOID;
52*4882a593Smuzhiyun 	}
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	/* Convert handle to full pathname and print it (with supplied message) */
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	status = acpi_ns_handle_to_pathname(node, &buffer, TRUE);
59*4882a593Smuzhiyun 	if (ACPI_SUCCESS(status)) {
60*4882a593Smuzhiyun 		if (message) {
61*4882a593Smuzhiyun 			ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "%s ",
62*4882a593Smuzhiyun 					      message));
63*4882a593Smuzhiyun 		}
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "[%s] (Node %p)",
66*4882a593Smuzhiyun 				      (char *)buffer.pointer, node));
67*4882a593Smuzhiyun 		ACPI_FREE(buffer.pointer);
68*4882a593Smuzhiyun 	}
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	return_VOID;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun /*******************************************************************************
74*4882a593Smuzhiyun  *
75*4882a593Smuzhiyun  * FUNCTION:    acpi_ds_dump_method_stack
76*4882a593Smuzhiyun  *
77*4882a593Smuzhiyun  * PARAMETERS:  status          - Method execution status
78*4882a593Smuzhiyun  *              walk_state      - Current state of the parse tree walk
79*4882a593Smuzhiyun  *              op              - Executing parse op
80*4882a593Smuzhiyun  *
81*4882a593Smuzhiyun  * RETURN:      None
82*4882a593Smuzhiyun  *
83*4882a593Smuzhiyun  * DESCRIPTION: Called when a method has been aborted because of an error.
84*4882a593Smuzhiyun  *              Dumps the method execution stack.
85*4882a593Smuzhiyun  *
86*4882a593Smuzhiyun  ******************************************************************************/
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun void
acpi_ds_dump_method_stack(acpi_status status,struct acpi_walk_state * walk_state,union acpi_parse_object * op)89*4882a593Smuzhiyun acpi_ds_dump_method_stack(acpi_status status,
90*4882a593Smuzhiyun 			  struct acpi_walk_state *walk_state,
91*4882a593Smuzhiyun 			  union acpi_parse_object *op)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun 	union acpi_parse_object *next;
94*4882a593Smuzhiyun 	struct acpi_thread_state *thread;
95*4882a593Smuzhiyun 	struct acpi_walk_state *next_walk_state;
96*4882a593Smuzhiyun 	struct acpi_namespace_node *previous_method = NULL;
97*4882a593Smuzhiyun 	union acpi_operand_object *method_desc;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ds_dump_method_stack);
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	/* Ignore control codes, they are not errors */
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	if ((status & AE_CODE_MASK) == AE_CODE_CONTROL) {
104*4882a593Smuzhiyun 		return_VOID;
105*4882a593Smuzhiyun 	}
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	/* We may be executing a deferred opcode */
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	if (walk_state->deferred_node) {
110*4882a593Smuzhiyun 		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
111*4882a593Smuzhiyun 				  "Executing subtree for Buffer/Package/Region\n"));
112*4882a593Smuzhiyun 		return_VOID;
113*4882a593Smuzhiyun 	}
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	/*
116*4882a593Smuzhiyun 	 * If there is no Thread, we are not actually executing a method.
117*4882a593Smuzhiyun 	 * This can happen when the iASL compiler calls the interpreter
118*4882a593Smuzhiyun 	 * to perform constant folding.
119*4882a593Smuzhiyun 	 */
120*4882a593Smuzhiyun 	thread = walk_state->thread;
121*4882a593Smuzhiyun 	if (!thread) {
122*4882a593Smuzhiyun 		return_VOID;
123*4882a593Smuzhiyun 	}
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	/* Display exception and method name */
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
128*4882a593Smuzhiyun 			  "\n**** Exception %s during execution of method ",
129*4882a593Smuzhiyun 			  acpi_format_exception(status)));
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	acpi_ds_print_node_pathname(walk_state->method_node, NULL);
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	/* Display stack of executing methods */
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH,
136*4882a593Smuzhiyun 			      "\n\nMethod Execution Stack:\n"));
137*4882a593Smuzhiyun 	next_walk_state = thread->walk_state_list;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	/* Walk list of linked walk states */
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	while (next_walk_state) {
142*4882a593Smuzhiyun 		method_desc = next_walk_state->method_desc;
143*4882a593Smuzhiyun 		if (method_desc) {
144*4882a593Smuzhiyun 			acpi_ex_stop_trace_method((struct acpi_namespace_node *)
145*4882a593Smuzhiyun 						  method_desc->method.node,
146*4882a593Smuzhiyun 						  method_desc, walk_state);
147*4882a593Smuzhiyun 		}
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
150*4882a593Smuzhiyun 				  "    Method [%4.4s] executing: ",
151*4882a593Smuzhiyun 				  acpi_ut_get_node_name(next_walk_state->
152*4882a593Smuzhiyun 							method_node)));
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 		/* First method is the currently executing method */
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 		if (next_walk_state == walk_state) {
157*4882a593Smuzhiyun 			if (op) {
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 				/* Display currently executing ASL statement */
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 				next = op->common.next;
162*4882a593Smuzhiyun 				op->common.next = NULL;
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun #ifdef ACPI_DISASSEMBLER
165*4882a593Smuzhiyun 				if (walk_state->method_node !=
166*4882a593Smuzhiyun 				    acpi_gbl_root_node) {
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 					/* More verbose if not module-level code */
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 					acpi_os_printf("Failed at ");
171*4882a593Smuzhiyun 					acpi_dm_disassemble(next_walk_state, op,
172*4882a593Smuzhiyun 							    ACPI_UINT32_MAX);
173*4882a593Smuzhiyun 				}
174*4882a593Smuzhiyun #endif
175*4882a593Smuzhiyun 				op->common.next = next;
176*4882a593Smuzhiyun 			}
177*4882a593Smuzhiyun 		} else {
178*4882a593Smuzhiyun 			/*
179*4882a593Smuzhiyun 			 * This method has called another method
180*4882a593Smuzhiyun 			 * NOTE: the method call parse subtree is already deleted at
181*4882a593Smuzhiyun 			 * this point, so we cannot disassemble the method invocation.
182*4882a593Smuzhiyun 			 */
183*4882a593Smuzhiyun 			ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH,
184*4882a593Smuzhiyun 					      "Call to method "));
185*4882a593Smuzhiyun 			acpi_ds_print_node_pathname(previous_method, NULL);
186*4882a593Smuzhiyun 		}
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 		previous_method = next_walk_state->method_node;
189*4882a593Smuzhiyun 		next_walk_state = next_walk_state->next;
190*4882a593Smuzhiyun 		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "\n"));
191*4882a593Smuzhiyun 	}
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	return_VOID;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun #else
197*4882a593Smuzhiyun void
198*4882a593Smuzhiyun acpi_ds_dump_method_stack(acpi_status status,
199*4882a593Smuzhiyun 			  struct acpi_walk_state *walk_state,
200*4882a593Smuzhiyun 			  union acpi_parse_object *op)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	return;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun #endif
206