nds32: fix build error "relocation truncated to fit: R_NDS32_25_PCREL_RELA" when
[linux-2.6-microblaze.git] / drivers / acpi / acpica / dbxface.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /*******************************************************************************
3  *
4  * Module Name: dbxface - AML Debugger external interfaces
5  *
6  ******************************************************************************/
7
8 #include <acpi/acpi.h>
9 #include "accommon.h"
10 #include "amlcode.h"
11 #include "acdebug.h"
12 #include "acinterp.h"
13
14 #define _COMPONENT          ACPI_CA_DEBUGGER
15 ACPI_MODULE_NAME("dbxface")
16
17 /* Local prototypes */
18 static acpi_status
19 acpi_db_start_command(struct acpi_walk_state *walk_state,
20                       union acpi_parse_object *op);
21
22 #ifdef ACPI_OBSOLETE_FUNCTIONS
23 void 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
39 static acpi_status
40 acpi_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;
53
54         while (status == AE_CTRL_TRUE) {
55
56                 /* Notify the completion of the command */
57
58                 status = acpi_os_notify_command_complete();
59                 if (ACPI_FAILURE(status)) {
60                         goto error_exit;
61                 }
62
63                 /* Wait the readiness of the command */
64
65                 status = acpi_os_wait_command_ready();
66                 if (ACPI_FAILURE(status)) {
67                         goto error_exit;
68                 }
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
77 error_exit:
78         if (ACPI_FAILURE(status) && status != AE_CTRL_TERMINATE) {
79                 ACPI_EXCEPTION((AE_INFO, status,
80                                 "While parsing/handling command line"));
81         }
82         return (status);
83 }
84
85 /*******************************************************************************
86  *
87  * FUNCTION:    acpi_db_signal_break_point
88  *
89  * PARAMETERS:  walk_state      - Current walk
90  *
91  * RETURN:      Status
92  *
93  * DESCRIPTION: Called for AML_BREAKPOINT_OP
94  *
95  ******************************************************************************/
96
97 void 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  *
117  * 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
129 acpi_status
130 acpi_db_single_step(struct acpi_walk_state *walk_state,
131                     union acpi_parse_object *op, u32 opcode_class)
132 {
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
142 #ifndef ACPI_APPLICATION
143         if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) {
144                 return (AE_OK);
145         }
146 #endif
147
148         /* 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
211                             ("\nAML Debug: Next AML Opcode to execute:\n");
212                 }
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
336         acpi_ex_exit_interpreter();
337         status = acpi_db_start_command(walk_state, op);
338         acpi_ex_enter_interpreter();
339
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
357 acpi_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
387         /* Initialize user commands loop */
388
389         acpi_gbl_db_terminate_loop = FALSE;
390
391         /*
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
400                 status = acpi_os_initialize_debugger();
401                 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
408                 acpi_gbl_db_threads_terminated = FALSE;
409                 status = acpi_os_execute(OSL_DEBUGGER_MAIN_THREAD,
410                                          acpi_db_execute_thread, NULL);
411                 if (ACPI_FAILURE(status)) {
412                         ACPI_EXCEPTION((AE_INFO, status,
413                                         "Could not start debugger thread"));
414                         acpi_gbl_db_threads_terminated = TRUE;
415                         return_ACPI_STATUS(status);
416                 }
417         } else {
418                 acpi_gbl_db_thread_id = acpi_os_get_thread_id();
419         }
420
421         return_ACPI_STATUS(AE_OK);
422 }
423
424 ACPI_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  ******************************************************************************/
437 void acpi_terminate_debugger(void)
438 {
439
440         /* Terminate the AML Debugger */
441
442         acpi_gbl_db_terminate_loop = TRUE;
443
444         if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
445
446                 /* Wait the AML Debugger threads */
447
448                 while (!acpi_gbl_db_threads_terminated) {
449                         acpi_os_sleep(100);
450                 }
451
452                 acpi_os_terminate_debugger();
453         }
454
455         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
465 ACPI_EXPORT_SYMBOL(acpi_terminate_debugger)
466
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  ******************************************************************************/
478 void acpi_set_debugger_thread_id(acpi_thread_id thread_id)
479 {
480         acpi_gbl_db_thread_id = thread_id;
481 }
482
483 ACPI_EXPORT_SYMBOL(acpi_set_debugger_thread_id)