162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: dsdebug - Parser/Interpreter interface - debugging 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2000 - 2023, Intel Corp. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci *****************************************************************************/ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <acpi/acpi.h> 1162306a36Sopenharmony_ci#include "accommon.h" 1262306a36Sopenharmony_ci#include "acdispat.h" 1362306a36Sopenharmony_ci#include "acnamesp.h" 1462306a36Sopenharmony_ci#ifdef ACPI_DISASSEMBLER 1562306a36Sopenharmony_ci#include "acdisasm.h" 1662306a36Sopenharmony_ci#endif 1762306a36Sopenharmony_ci#include "acinterp.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define _COMPONENT ACPI_DISPATCHER 2062306a36Sopenharmony_ciACPI_MODULE_NAME("dsdebug") 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) 2362306a36Sopenharmony_ci/* Local prototypes */ 2462306a36Sopenharmony_cistatic void 2562306a36Sopenharmony_ciacpi_ds_print_node_pathname(struct acpi_namespace_node *node, 2662306a36Sopenharmony_ci const char *message); 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci/******************************************************************************* 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * FUNCTION: acpi_ds_print_node_pathname 3162306a36Sopenharmony_ci * 3262306a36Sopenharmony_ci * PARAMETERS: node - Object 3362306a36Sopenharmony_ci * message - Prefix message 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * DESCRIPTION: Print an object's full namespace pathname 3662306a36Sopenharmony_ci * Manages allocation/freeing of a pathname buffer 3762306a36Sopenharmony_ci * 3862306a36Sopenharmony_ci ******************************************************************************/ 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic void 4162306a36Sopenharmony_ciacpi_ds_print_node_pathname(struct acpi_namespace_node *node, 4262306a36Sopenharmony_ci const char *message) 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci struct acpi_buffer buffer; 4562306a36Sopenharmony_ci acpi_status status; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ds_print_node_pathname); 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci if (!node) { 5062306a36Sopenharmony_ci ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "[NULL NAME]")); 5162306a36Sopenharmony_ci return_VOID; 5262306a36Sopenharmony_ci } 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci /* Convert handle to full pathname and print it (with supplied message) */ 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci status = acpi_ns_handle_to_pathname(node, &buffer, TRUE); 5962306a36Sopenharmony_ci if (ACPI_SUCCESS(status)) { 6062306a36Sopenharmony_ci if (message) { 6162306a36Sopenharmony_ci ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "%s ", 6262306a36Sopenharmony_ci message)); 6362306a36Sopenharmony_ci } 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "[%s] (Node %p)", 6662306a36Sopenharmony_ci (char *)buffer.pointer, node)); 6762306a36Sopenharmony_ci ACPI_FREE(buffer.pointer); 6862306a36Sopenharmony_ci } 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci return_VOID; 7162306a36Sopenharmony_ci} 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci/******************************************************************************* 7462306a36Sopenharmony_ci * 7562306a36Sopenharmony_ci * FUNCTION: acpi_ds_dump_method_stack 7662306a36Sopenharmony_ci * 7762306a36Sopenharmony_ci * PARAMETERS: status - Method execution status 7862306a36Sopenharmony_ci * walk_state - Current state of the parse tree walk 7962306a36Sopenharmony_ci * op - Executing parse op 8062306a36Sopenharmony_ci * 8162306a36Sopenharmony_ci * RETURN: None 8262306a36Sopenharmony_ci * 8362306a36Sopenharmony_ci * DESCRIPTION: Called when a method has been aborted because of an error. 8462306a36Sopenharmony_ci * Dumps the method execution stack. 8562306a36Sopenharmony_ci * 8662306a36Sopenharmony_ci ******************************************************************************/ 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_civoid 8962306a36Sopenharmony_ciacpi_ds_dump_method_stack(acpi_status status, 9062306a36Sopenharmony_ci struct acpi_walk_state *walk_state, 9162306a36Sopenharmony_ci union acpi_parse_object *op) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci union acpi_parse_object *next; 9462306a36Sopenharmony_ci struct acpi_thread_state *thread; 9562306a36Sopenharmony_ci struct acpi_walk_state *next_walk_state; 9662306a36Sopenharmony_ci struct acpi_namespace_node *previous_method = NULL; 9762306a36Sopenharmony_ci union acpi_operand_object *method_desc; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ds_dump_method_stack); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci /* Ignore control codes, they are not errors */ 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci if (ACPI_CNTL_EXCEPTION(status)) { 10462306a36Sopenharmony_ci return_VOID; 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci /* We may be executing a deferred opcode */ 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci if (walk_state->deferred_node) { 11062306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 11162306a36Sopenharmony_ci "Executing subtree for Buffer/Package/Region\n")); 11262306a36Sopenharmony_ci return_VOID; 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci /* 11662306a36Sopenharmony_ci * If there is no Thread, we are not actually executing a method. 11762306a36Sopenharmony_ci * This can happen when the iASL compiler calls the interpreter 11862306a36Sopenharmony_ci * to perform constant folding. 11962306a36Sopenharmony_ci */ 12062306a36Sopenharmony_ci thread = walk_state->thread; 12162306a36Sopenharmony_ci if (!thread) { 12262306a36Sopenharmony_ci return_VOID; 12362306a36Sopenharmony_ci } 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci /* Display exception and method name */ 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 12862306a36Sopenharmony_ci "\n**** Exception %s during execution of method ", 12962306a36Sopenharmony_ci acpi_format_exception(status))); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci acpi_ds_print_node_pathname(walk_state->method_node, NULL); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci /* Display stack of executing methods */ 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, 13662306a36Sopenharmony_ci "\n\nMethod Execution Stack:\n")); 13762306a36Sopenharmony_ci next_walk_state = thread->walk_state_list; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci /* Walk list of linked walk states */ 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci while (next_walk_state) { 14262306a36Sopenharmony_ci method_desc = next_walk_state->method_desc; 14362306a36Sopenharmony_ci if (method_desc) { 14462306a36Sopenharmony_ci acpi_ex_stop_trace_method((struct acpi_namespace_node *) 14562306a36Sopenharmony_ci method_desc->method.node, 14662306a36Sopenharmony_ci method_desc, walk_state); 14762306a36Sopenharmony_ci } 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 15062306a36Sopenharmony_ci " Method [%4.4s] executing: ", 15162306a36Sopenharmony_ci acpi_ut_get_node_name(next_walk_state-> 15262306a36Sopenharmony_ci method_node))); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci /* First method is the currently executing method */ 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci if (next_walk_state == walk_state) { 15762306a36Sopenharmony_ci if (op) { 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci /* Display currently executing ASL statement */ 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci next = op->common.next; 16262306a36Sopenharmony_ci op->common.next = NULL; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci#ifdef ACPI_DISASSEMBLER 16562306a36Sopenharmony_ci if (walk_state->method_node != 16662306a36Sopenharmony_ci acpi_gbl_root_node) { 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci /* More verbose if not module-level code */ 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci acpi_os_printf("Failed at "); 17162306a36Sopenharmony_ci acpi_dm_disassemble(next_walk_state, op, 17262306a36Sopenharmony_ci ACPI_UINT32_MAX); 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci#endif 17562306a36Sopenharmony_ci op->common.next = next; 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci } else { 17862306a36Sopenharmony_ci /* 17962306a36Sopenharmony_ci * This method has called another method 18062306a36Sopenharmony_ci * NOTE: the method call parse subtree is already deleted at 18162306a36Sopenharmony_ci * this point, so we cannot disassemble the method invocation. 18262306a36Sopenharmony_ci */ 18362306a36Sopenharmony_ci ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, 18462306a36Sopenharmony_ci "Call to method ")); 18562306a36Sopenharmony_ci acpi_ds_print_node_pathname(previous_method, NULL); 18662306a36Sopenharmony_ci } 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci previous_method = next_walk_state->method_node; 18962306a36Sopenharmony_ci next_walk_state = next_walk_state->next; 19062306a36Sopenharmony_ci ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "\n")); 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci return_VOID; 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci#else 19762306a36Sopenharmony_civoid 19862306a36Sopenharmony_ciacpi_ds_dump_method_stack(acpi_status status, 19962306a36Sopenharmony_ci struct acpi_walk_state *walk_state, 20062306a36Sopenharmony_ci union acpi_parse_object *op) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci return; 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci#endif 206