xref: /OK3568_Linux_fs/kernel/drivers/acpi/acpica/dbxface.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /*******************************************************************************
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Module Name: dbxface - AML Debugger external interfaces
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  ******************************************************************************/
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <acpi/acpi.h>
9*4882a593Smuzhiyun #include "accommon.h"
10*4882a593Smuzhiyun #include "amlcode.h"
11*4882a593Smuzhiyun #include "acdebug.h"
12*4882a593Smuzhiyun #include "acinterp.h"
13*4882a593Smuzhiyun #include "acparser.h"
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #define _COMPONENT          ACPI_CA_DEBUGGER
16*4882a593Smuzhiyun ACPI_MODULE_NAME("dbxface")
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun /* Local prototypes */
19*4882a593Smuzhiyun static acpi_status
20*4882a593Smuzhiyun acpi_db_start_command(struct acpi_walk_state *walk_state,
21*4882a593Smuzhiyun 		      union acpi_parse_object *op);
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #ifdef ACPI_OBSOLETE_FUNCTIONS
24*4882a593Smuzhiyun void acpi_db_method_end(struct acpi_walk_state *walk_state);
25*4882a593Smuzhiyun #endif
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #ifdef ACPI_DISASSEMBLER
28*4882a593Smuzhiyun static union acpi_parse_object *acpi_db_get_display_op(struct acpi_walk_state
29*4882a593Smuzhiyun 						       *walk_state,
30*4882a593Smuzhiyun 						       union acpi_parse_object
31*4882a593Smuzhiyun 						       *op);
32*4882a593Smuzhiyun #endif
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun /*******************************************************************************
35*4882a593Smuzhiyun  *
36*4882a593Smuzhiyun  * FUNCTION:    acpi_db_start_command
37*4882a593Smuzhiyun  *
38*4882a593Smuzhiyun  * PARAMETERS:  walk_state      - Current walk
39*4882a593Smuzhiyun  *              op              - Current executing Op, from AML interpreter
40*4882a593Smuzhiyun  *
41*4882a593Smuzhiyun  * RETURN:      Status
42*4882a593Smuzhiyun  *
43*4882a593Smuzhiyun  * DESCRIPTION: Enter debugger command loop
44*4882a593Smuzhiyun  *
45*4882a593Smuzhiyun  ******************************************************************************/
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun static acpi_status
acpi_db_start_command(struct acpi_walk_state * walk_state,union acpi_parse_object * op)48*4882a593Smuzhiyun acpi_db_start_command(struct acpi_walk_state *walk_state,
49*4882a593Smuzhiyun 		      union acpi_parse_object *op)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun 	acpi_status status;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	/* TBD: [Investigate] are there namespace locking issues here? */
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	/* acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); */
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	/* Go into the command loop and await next user command */
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	acpi_gbl_method_executing = TRUE;
60*4882a593Smuzhiyun 	status = AE_CTRL_TRUE;
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 	while (status == AE_CTRL_TRUE) {
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 		/* Notify the completion of the command */
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 		status = acpi_os_notify_command_complete();
67*4882a593Smuzhiyun 		if (ACPI_FAILURE(status)) {
68*4882a593Smuzhiyun 			goto error_exit;
69*4882a593Smuzhiyun 		}
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 		/* Wait the readiness of the command */
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 		status = acpi_os_wait_command_ready();
74*4882a593Smuzhiyun 		if (ACPI_FAILURE(status)) {
75*4882a593Smuzhiyun 			goto error_exit;
76*4882a593Smuzhiyun 		}
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 		status =
79*4882a593Smuzhiyun 		    acpi_db_command_dispatch(acpi_gbl_db_line_buf, walk_state,
80*4882a593Smuzhiyun 					     op);
81*4882a593Smuzhiyun 	}
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	/* acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); */
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun error_exit:
86*4882a593Smuzhiyun 	if (ACPI_FAILURE(status) && status != AE_CTRL_TERMINATE) {
87*4882a593Smuzhiyun 		ACPI_EXCEPTION((AE_INFO, status,
88*4882a593Smuzhiyun 				"While parsing/handling command line"));
89*4882a593Smuzhiyun 	}
90*4882a593Smuzhiyun 	return (status);
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun /*******************************************************************************
94*4882a593Smuzhiyun  *
95*4882a593Smuzhiyun  * FUNCTION:    acpi_db_signal_break_point
96*4882a593Smuzhiyun  *
97*4882a593Smuzhiyun  * PARAMETERS:  walk_state      - Current walk
98*4882a593Smuzhiyun  *
99*4882a593Smuzhiyun  * RETURN:      Status
100*4882a593Smuzhiyun  *
101*4882a593Smuzhiyun  * DESCRIPTION: Called for AML_BREAKPOINT_OP
102*4882a593Smuzhiyun  *
103*4882a593Smuzhiyun  ******************************************************************************/
104*4882a593Smuzhiyun 
acpi_db_signal_break_point(struct acpi_walk_state * walk_state)105*4882a593Smuzhiyun void acpi_db_signal_break_point(struct acpi_walk_state *walk_state)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun #ifndef ACPI_APPLICATION
109*4882a593Smuzhiyun 	if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) {
110*4882a593Smuzhiyun 		return;
111*4882a593Smuzhiyun 	}
112*4882a593Smuzhiyun #endif
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	/*
115*4882a593Smuzhiyun 	 * Set the single-step flag. This will cause the debugger (if present)
116*4882a593Smuzhiyun 	 * to break to the console within the AML debugger at the start of the
117*4882a593Smuzhiyun 	 * next AML instruction.
118*4882a593Smuzhiyun 	 */
119*4882a593Smuzhiyun 	acpi_gbl_cm_single_step = TRUE;
120*4882a593Smuzhiyun 	acpi_os_printf("**break** Executed AML BreakPoint opcode\n");
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun #ifdef ACPI_DISASSEMBLER
124*4882a593Smuzhiyun /*******************************************************************************
125*4882a593Smuzhiyun  *
126*4882a593Smuzhiyun  * FUNCTION:    acpi_db_get_display_op
127*4882a593Smuzhiyun  *
128*4882a593Smuzhiyun  * PARAMETERS:  walk_state      - Current walk
129*4882a593Smuzhiyun  *              op              - Current executing op (from aml interpreter)
130*4882a593Smuzhiyun  *
131*4882a593Smuzhiyun  * RETURN:      Opcode to display
132*4882a593Smuzhiyun  *
133*4882a593Smuzhiyun  * DESCRIPTION: Find the opcode to display during single stepping
134*4882a593Smuzhiyun  *
135*4882a593Smuzhiyun  ******************************************************************************/
136*4882a593Smuzhiyun 
acpi_db_get_display_op(struct acpi_walk_state * walk_state,union acpi_parse_object * op)137*4882a593Smuzhiyun static union acpi_parse_object *acpi_db_get_display_op(struct acpi_walk_state
138*4882a593Smuzhiyun 						       *walk_state,
139*4882a593Smuzhiyun 						       union acpi_parse_object
140*4882a593Smuzhiyun 						       *op)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun 	union acpi_parse_object *display_op;
143*4882a593Smuzhiyun 	union acpi_parse_object *parent_op;
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	display_op = op;
146*4882a593Smuzhiyun 	parent_op = op->common.parent;
147*4882a593Smuzhiyun 	if (parent_op) {
148*4882a593Smuzhiyun 		if ((walk_state->control_state) &&
149*4882a593Smuzhiyun 		    (walk_state->control_state->common.state ==
150*4882a593Smuzhiyun 		     ACPI_CONTROL_PREDICATE_EXECUTING)) {
151*4882a593Smuzhiyun 			/*
152*4882a593Smuzhiyun 			 * We are executing the predicate of an IF or WHILE statement
153*4882a593Smuzhiyun 			 * Search upwards for the containing IF or WHILE so that the
154*4882a593Smuzhiyun 			 * entire predicate can be displayed.
155*4882a593Smuzhiyun 			 */
156*4882a593Smuzhiyun 			while (parent_op) {
157*4882a593Smuzhiyun 				if ((parent_op->common.aml_opcode == AML_IF_OP)
158*4882a593Smuzhiyun 				    || (parent_op->common.aml_opcode ==
159*4882a593Smuzhiyun 					AML_WHILE_OP)) {
160*4882a593Smuzhiyun 					display_op = parent_op;
161*4882a593Smuzhiyun 					break;
162*4882a593Smuzhiyun 				}
163*4882a593Smuzhiyun 				parent_op = parent_op->common.parent;
164*4882a593Smuzhiyun 			}
165*4882a593Smuzhiyun 		} else {
166*4882a593Smuzhiyun 			while (parent_op) {
167*4882a593Smuzhiyun 				if ((parent_op->common.aml_opcode == AML_IF_OP)
168*4882a593Smuzhiyun 				    || (parent_op->common.aml_opcode ==
169*4882a593Smuzhiyun 					AML_ELSE_OP)
170*4882a593Smuzhiyun 				    || (parent_op->common.aml_opcode ==
171*4882a593Smuzhiyun 					AML_SCOPE_OP)
172*4882a593Smuzhiyun 				    || (parent_op->common.aml_opcode ==
173*4882a593Smuzhiyun 					AML_METHOD_OP)
174*4882a593Smuzhiyun 				    || (parent_op->common.aml_opcode ==
175*4882a593Smuzhiyun 					AML_WHILE_OP)) {
176*4882a593Smuzhiyun 					break;
177*4882a593Smuzhiyun 				}
178*4882a593Smuzhiyun 				display_op = parent_op;
179*4882a593Smuzhiyun 				parent_op = parent_op->common.parent;
180*4882a593Smuzhiyun 			}
181*4882a593Smuzhiyun 		}
182*4882a593Smuzhiyun 	}
183*4882a593Smuzhiyun 	return display_op;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun #endif
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun /*******************************************************************************
188*4882a593Smuzhiyun  *
189*4882a593Smuzhiyun  * FUNCTION:    acpi_db_single_step
190*4882a593Smuzhiyun  *
191*4882a593Smuzhiyun  * PARAMETERS:  walk_state      - Current walk
192*4882a593Smuzhiyun  *              op              - Current executing op (from aml interpreter)
193*4882a593Smuzhiyun  *              opcode_class    - Class of the current AML Opcode
194*4882a593Smuzhiyun  *
195*4882a593Smuzhiyun  * RETURN:      Status
196*4882a593Smuzhiyun  *
197*4882a593Smuzhiyun  * DESCRIPTION: Called just before execution of an AML opcode.
198*4882a593Smuzhiyun  *
199*4882a593Smuzhiyun  ******************************************************************************/
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun acpi_status
acpi_db_single_step(struct acpi_walk_state * walk_state,union acpi_parse_object * op,u32 opcode_class)202*4882a593Smuzhiyun acpi_db_single_step(struct acpi_walk_state *walk_state,
203*4882a593Smuzhiyun 		    union acpi_parse_object *op, u32 opcode_class)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun 	union acpi_parse_object *next;
206*4882a593Smuzhiyun 	acpi_status status = AE_OK;
207*4882a593Smuzhiyun 	u32 original_debug_level;
208*4882a593Smuzhiyun 	u32 aml_offset;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	ACPI_FUNCTION_ENTRY();
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun #ifndef ACPI_APPLICATION
213*4882a593Smuzhiyun 	if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) {
214*4882a593Smuzhiyun 		return (AE_OK);
215*4882a593Smuzhiyun 	}
216*4882a593Smuzhiyun #endif
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	/* Check the abort flag */
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	if (acpi_gbl_abort_method) {
221*4882a593Smuzhiyun 		acpi_gbl_abort_method = FALSE;
222*4882a593Smuzhiyun 		return (AE_ABORT_METHOD);
223*4882a593Smuzhiyun 	}
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	aml_offset = (u32)ACPI_PTR_DIFF(op->common.aml,
226*4882a593Smuzhiyun 					walk_state->parser_state.aml_start);
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	/* Check for single-step breakpoint */
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	if (walk_state->method_breakpoint &&
231*4882a593Smuzhiyun 	    (walk_state->method_breakpoint <= aml_offset)) {
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 		/* Check if the breakpoint has been reached or passed */
234*4882a593Smuzhiyun 		/* Hit the breakpoint, resume single step, reset breakpoint */
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 		acpi_os_printf("***Break*** at AML offset %X\n", aml_offset);
237*4882a593Smuzhiyun 		acpi_gbl_cm_single_step = TRUE;
238*4882a593Smuzhiyun 		acpi_gbl_step_to_next_call = FALSE;
239*4882a593Smuzhiyun 		walk_state->method_breakpoint = 0;
240*4882a593Smuzhiyun 	}
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	/* Check for user breakpoint (Must be on exact Aml offset) */
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	else if (walk_state->user_breakpoint &&
245*4882a593Smuzhiyun 		 (walk_state->user_breakpoint == aml_offset)) {
246*4882a593Smuzhiyun 		acpi_os_printf("***UserBreakpoint*** at AML offset %X\n",
247*4882a593Smuzhiyun 			       aml_offset);
248*4882a593Smuzhiyun 		acpi_gbl_cm_single_step = TRUE;
249*4882a593Smuzhiyun 		acpi_gbl_step_to_next_call = FALSE;
250*4882a593Smuzhiyun 		walk_state->method_breakpoint = 0;
251*4882a593Smuzhiyun 	}
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	/*
254*4882a593Smuzhiyun 	 * Check if this is an opcode that we are interested in --
255*4882a593Smuzhiyun 	 * namely, opcodes that have arguments
256*4882a593Smuzhiyun 	 */
257*4882a593Smuzhiyun 	if (op->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
258*4882a593Smuzhiyun 		return (AE_OK);
259*4882a593Smuzhiyun 	}
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	switch (opcode_class) {
262*4882a593Smuzhiyun 	case AML_CLASS_UNKNOWN:
263*4882a593Smuzhiyun 	case AML_CLASS_ARGUMENT:	/* constants, literals, etc. do nothing */
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 		return (AE_OK);
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	default:
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 		/* All other opcodes -- continue */
270*4882a593Smuzhiyun 		break;
271*4882a593Smuzhiyun 	}
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	/*
274*4882a593Smuzhiyun 	 * Under certain debug conditions, display this opcode and its operands
275*4882a593Smuzhiyun 	 */
276*4882a593Smuzhiyun 	if ((acpi_gbl_db_output_to_file) ||
277*4882a593Smuzhiyun 	    (acpi_gbl_cm_single_step) || (acpi_dbg_level & ACPI_LV_PARSE)) {
278*4882a593Smuzhiyun 		if ((acpi_gbl_db_output_to_file) ||
279*4882a593Smuzhiyun 		    (acpi_dbg_level & ACPI_LV_PARSE)) {
280*4882a593Smuzhiyun 			acpi_os_printf
281*4882a593Smuzhiyun 			    ("\nAML Debug: Next AML Opcode to execute:\n");
282*4882a593Smuzhiyun 		}
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 		/*
285*4882a593Smuzhiyun 		 * Display this op (and only this op - zero out the NEXT field
286*4882a593Smuzhiyun 		 * temporarily, and disable parser trace output for the duration of
287*4882a593Smuzhiyun 		 * the display because we don't want the extraneous debug output)
288*4882a593Smuzhiyun 		 */
289*4882a593Smuzhiyun 		original_debug_level = acpi_dbg_level;
290*4882a593Smuzhiyun 		acpi_dbg_level &= ~(ACPI_LV_PARSE | ACPI_LV_FUNCTIONS);
291*4882a593Smuzhiyun 		next = op->common.next;
292*4882a593Smuzhiyun 		op->common.next = NULL;
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 		/* Now we can disassemble and display it */
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun #ifdef ACPI_DISASSEMBLER
297*4882a593Smuzhiyun 		acpi_dm_disassemble(walk_state,
298*4882a593Smuzhiyun 				    acpi_db_get_display_op(walk_state, op),
299*4882a593Smuzhiyun 				    ACPI_UINT32_MAX);
300*4882a593Smuzhiyun #else
301*4882a593Smuzhiyun 		/*
302*4882a593Smuzhiyun 		 * The AML Disassembler is not configured - at least we can
303*4882a593Smuzhiyun 		 * display the opcode value and name
304*4882a593Smuzhiyun 		 */
305*4882a593Smuzhiyun 		acpi_os_printf("AML Opcode: %4.4X %s\n", op->common.aml_opcode,
306*4882a593Smuzhiyun 			       acpi_ps_get_opcode_name(op->common.aml_opcode));
307*4882a593Smuzhiyun #endif
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 		if ((op->common.aml_opcode == AML_IF_OP) ||
310*4882a593Smuzhiyun 		    (op->common.aml_opcode == AML_WHILE_OP)) {
311*4882a593Smuzhiyun 			if (walk_state->control_state->common.value) {
312*4882a593Smuzhiyun 				acpi_os_printf
313*4882a593Smuzhiyun 				    ("Predicate = [True], IF block was executed\n");
314*4882a593Smuzhiyun 			} else {
315*4882a593Smuzhiyun 				acpi_os_printf
316*4882a593Smuzhiyun 				    ("Predicate = [False], Skipping IF block\n");
317*4882a593Smuzhiyun 			}
318*4882a593Smuzhiyun 		} else if (op->common.aml_opcode == AML_ELSE_OP) {
319*4882a593Smuzhiyun 			acpi_os_printf
320*4882a593Smuzhiyun 			    ("Predicate = [False], ELSE block was executed\n");
321*4882a593Smuzhiyun 		}
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 		/* Restore everything */
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 		op->common.next = next;
326*4882a593Smuzhiyun 		acpi_os_printf("\n");
327*4882a593Smuzhiyun 		if ((acpi_gbl_db_output_to_file) ||
328*4882a593Smuzhiyun 		    (acpi_dbg_level & ACPI_LV_PARSE)) {
329*4882a593Smuzhiyun 			acpi_os_printf("\n");
330*4882a593Smuzhiyun 		}
331*4882a593Smuzhiyun 		acpi_dbg_level = original_debug_level;
332*4882a593Smuzhiyun 	}
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	/* If we are not single stepping, just continue executing the method */
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	if (!acpi_gbl_cm_single_step) {
337*4882a593Smuzhiyun 		return (AE_OK);
338*4882a593Smuzhiyun 	}
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	/*
341*4882a593Smuzhiyun 	 * If we are executing a step-to-call command,
342*4882a593Smuzhiyun 	 * Check if this is a method call.
343*4882a593Smuzhiyun 	 */
344*4882a593Smuzhiyun 	if (acpi_gbl_step_to_next_call) {
345*4882a593Smuzhiyun 		if (op->common.aml_opcode != AML_INT_METHODCALL_OP) {
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 			/* Not a method call, just keep executing */
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 			return (AE_OK);
350*4882a593Smuzhiyun 		}
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 		/* Found a method call, stop executing */
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 		acpi_gbl_step_to_next_call = FALSE;
355*4882a593Smuzhiyun 	}
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 	/*
358*4882a593Smuzhiyun 	 * If the next opcode is a method call, we will "step over" it
359*4882a593Smuzhiyun 	 * by default.
360*4882a593Smuzhiyun 	 */
361*4882a593Smuzhiyun 	if (op->common.aml_opcode == AML_INT_METHODCALL_OP) {
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 		/* Force no more single stepping while executing called method */
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 		acpi_gbl_cm_single_step = FALSE;
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 		/*
368*4882a593Smuzhiyun 		 * Set the breakpoint on/before the call, it will stop execution
369*4882a593Smuzhiyun 		 * as soon as we return
370*4882a593Smuzhiyun 		 */
371*4882a593Smuzhiyun 		walk_state->method_breakpoint = 1;	/* Must be non-zero! */
372*4882a593Smuzhiyun 	}
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	acpi_ex_exit_interpreter();
375*4882a593Smuzhiyun 	status = acpi_db_start_command(walk_state, op);
376*4882a593Smuzhiyun 	acpi_ex_enter_interpreter();
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	/* User commands complete, continue execution of the interrupted method */
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	return (status);
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun /*******************************************************************************
384*4882a593Smuzhiyun  *
385*4882a593Smuzhiyun  * FUNCTION:    acpi_initialize_debugger
386*4882a593Smuzhiyun  *
387*4882a593Smuzhiyun  * PARAMETERS:  None
388*4882a593Smuzhiyun  *
389*4882a593Smuzhiyun  * RETURN:      Status
390*4882a593Smuzhiyun  *
391*4882a593Smuzhiyun  * DESCRIPTION: Init and start debugger
392*4882a593Smuzhiyun  *
393*4882a593Smuzhiyun  ******************************************************************************/
394*4882a593Smuzhiyun 
acpi_initialize_debugger(void)395*4882a593Smuzhiyun acpi_status acpi_initialize_debugger(void)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun 	acpi_status status;
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(acpi_initialize_debugger);
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	/* Init globals */
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	acpi_gbl_db_buffer = NULL;
404*4882a593Smuzhiyun 	acpi_gbl_db_filename = NULL;
405*4882a593Smuzhiyun 	acpi_gbl_db_output_to_file = FALSE;
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 	acpi_gbl_db_debug_level = ACPI_LV_VERBOSITY2;
408*4882a593Smuzhiyun 	acpi_gbl_db_console_debug_level = ACPI_NORMAL_DEFAULT | ACPI_LV_TABLES;
409*4882a593Smuzhiyun 	acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	acpi_gbl_db_opt_no_ini_methods = FALSE;
412*4882a593Smuzhiyun 	acpi_gbl_db_opt_no_region_support = FALSE;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	acpi_gbl_db_buffer = acpi_os_allocate(ACPI_DEBUG_BUFFER_SIZE);
415*4882a593Smuzhiyun 	if (!acpi_gbl_db_buffer) {
416*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_NO_MEMORY);
417*4882a593Smuzhiyun 	}
418*4882a593Smuzhiyun 	memset(acpi_gbl_db_buffer, 0, ACPI_DEBUG_BUFFER_SIZE);
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 	/* Initial scope is the root */
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 	acpi_gbl_db_scope_buf[0] = AML_ROOT_PREFIX;
423*4882a593Smuzhiyun 	acpi_gbl_db_scope_buf[1] = 0;
424*4882a593Smuzhiyun 	acpi_gbl_db_scope_node = acpi_gbl_root_node;
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	/* Initialize user commands loop */
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	acpi_gbl_db_terminate_loop = FALSE;
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	/*
431*4882a593Smuzhiyun 	 * If configured for multi-thread support, the debug executor runs in
432*4882a593Smuzhiyun 	 * a separate thread so that the front end can be in another address
433*4882a593Smuzhiyun 	 * space, environment, or even another machine.
434*4882a593Smuzhiyun 	 */
435*4882a593Smuzhiyun 	if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 		/* These were created with one unit, grab it */
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 		status = acpi_os_initialize_debugger();
440*4882a593Smuzhiyun 		if (ACPI_FAILURE(status)) {
441*4882a593Smuzhiyun 			acpi_os_printf("Could not get debugger mutex\n");
442*4882a593Smuzhiyun 			return_ACPI_STATUS(status);
443*4882a593Smuzhiyun 		}
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun 		/* Create the debug execution thread to execute commands */
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 		acpi_gbl_db_threads_terminated = FALSE;
448*4882a593Smuzhiyun 		status = acpi_os_execute(OSL_DEBUGGER_MAIN_THREAD,
449*4882a593Smuzhiyun 					 acpi_db_execute_thread, NULL);
450*4882a593Smuzhiyun 		if (ACPI_FAILURE(status)) {
451*4882a593Smuzhiyun 			ACPI_EXCEPTION((AE_INFO, status,
452*4882a593Smuzhiyun 					"Could not start debugger thread"));
453*4882a593Smuzhiyun 			acpi_gbl_db_threads_terminated = TRUE;
454*4882a593Smuzhiyun 			return_ACPI_STATUS(status);
455*4882a593Smuzhiyun 		}
456*4882a593Smuzhiyun 	} else {
457*4882a593Smuzhiyun 		acpi_gbl_db_thread_id = acpi_os_get_thread_id();
458*4882a593Smuzhiyun 	}
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun 
ACPI_EXPORT_SYMBOL(acpi_initialize_debugger)463*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_initialize_debugger)
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun /*******************************************************************************
466*4882a593Smuzhiyun  *
467*4882a593Smuzhiyun  * FUNCTION:    acpi_terminate_debugger
468*4882a593Smuzhiyun  *
469*4882a593Smuzhiyun  * PARAMETERS:  None
470*4882a593Smuzhiyun  *
471*4882a593Smuzhiyun  * RETURN:      None
472*4882a593Smuzhiyun  *
473*4882a593Smuzhiyun  * DESCRIPTION: Stop debugger
474*4882a593Smuzhiyun  *
475*4882a593Smuzhiyun  ******************************************************************************/
476*4882a593Smuzhiyun void acpi_terminate_debugger(void)
477*4882a593Smuzhiyun {
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	/* Terminate the AML Debugger */
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	acpi_gbl_db_terminate_loop = TRUE;
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 		/* Wait the AML Debugger threads */
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 		while (!acpi_gbl_db_threads_terminated) {
488*4882a593Smuzhiyun 			acpi_os_sleep(100);
489*4882a593Smuzhiyun 		}
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 		acpi_os_terminate_debugger();
492*4882a593Smuzhiyun 	}
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	if (acpi_gbl_db_buffer) {
495*4882a593Smuzhiyun 		acpi_os_free(acpi_gbl_db_buffer);
496*4882a593Smuzhiyun 		acpi_gbl_db_buffer = NULL;
497*4882a593Smuzhiyun 	}
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	/* Ensure that debug output is now disabled */
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 	acpi_gbl_db_output_flags = ACPI_DB_DISABLE_OUTPUT;
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun 
ACPI_EXPORT_SYMBOL(acpi_terminate_debugger)504*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_terminate_debugger)
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun /*******************************************************************************
507*4882a593Smuzhiyun  *
508*4882a593Smuzhiyun  * FUNCTION:    acpi_set_debugger_thread_id
509*4882a593Smuzhiyun  *
510*4882a593Smuzhiyun  * PARAMETERS:  thread_id       - Debugger thread ID
511*4882a593Smuzhiyun  *
512*4882a593Smuzhiyun  * RETURN:      None
513*4882a593Smuzhiyun  *
514*4882a593Smuzhiyun  * DESCRIPTION: Set debugger thread ID
515*4882a593Smuzhiyun  *
516*4882a593Smuzhiyun  ******************************************************************************/
517*4882a593Smuzhiyun void acpi_set_debugger_thread_id(acpi_thread_id thread_id)
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun 	acpi_gbl_db_thread_id = thread_id;
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_set_debugger_thread_id)
523