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