ACPICA: Executer: Add interpreter tracing mode for method tracing facility
ACPICA commit 07fffd02607685b655ed92ee15c160e6a810b60b The acpi_debug_trace() is the mechanism known as ACPI method tracing that is used by Linux as ACPICA debugging message reducer. This facility can be controlled through Linux ACPI subsystem - /sys/module/acpi/parameters. This facility requires CONFIG_ACPI_DEBUG to be enabled to see ACPICA trace logs in the kernel dmesg output. This patch enhances acpi_debug_trace() to make it not only a message reducer, but a real tracer to trace AML interpreter execution. Note that in addition to the AML tracer enabling, this patch also updates the facility with the following enhancements: 1. Allow a full path to be specified by the acpi_debug_trace() API. 2. Allow any method rather than just the entrance of acpi_evaluate_object() to be traced. 3. All interpreter ACPI_LV_TRACE_POINT messages are collected for ACPI_EXECUTER layer. The Makefile of drivers/acpi/acpica is also updated to include exdebug.o and the duplicated stubs are removed after that. Note that since this patch has enhanced the method tracing facility, Linux need also be updated after applying this patch. Lv Zheng. Link: https://github.com/acpica/acpica/commit/07fffd02 Signed-off-by: Lv Zheng <lv.zheng@intel.com> Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:

committed by
Rafael J. Wysocki

parent
a616dc2fe5
commit
ab6c573320
@@ -43,11 +43,15 @@
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include "accommon.h"
|
||||
#include "acnamesp.h"
|
||||
#include "acinterp.h"
|
||||
#include "acparser.h"
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME("exdebug")
|
||||
|
||||
static union acpi_operand_object *acpi_gbl_trace_method_object = NULL;
|
||||
|
||||
#ifndef ACPI_NO_ERROR_MESSAGES
|
||||
/*******************************************************************************
|
||||
*
|
||||
@@ -70,6 +74,7 @@ ACPI_MODULE_NAME("exdebug")
|
||||
* enabled if necessary.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
|
||||
u32 level, u32 index)
|
||||
@@ -308,3 +313,269 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
|
||||
return_VOID;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_interpreter_trace_enabled
|
||||
*
|
||||
* PARAMETERS: name - Whether method name should be matched,
|
||||
* this should be checked before starting
|
||||
* the tracer
|
||||
*
|
||||
* RETURN: TRUE if interpreter trace is enabled.
|
||||
*
|
||||
* DESCRIPTION: Check whether interpreter trace is enabled
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static u8 acpi_ex_interpreter_trace_enabled(char *name)
|
||||
{
|
||||
|
||||
/* Check if tracing is enabled */
|
||||
|
||||
if (!(acpi_gbl_trace_flags & ACPI_TRACE_ENABLED)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if tracing is filtered:
|
||||
*
|
||||
* 1. If the tracer is started, acpi_gbl_trace_method_object should have
|
||||
* been filled by the trace starter
|
||||
* 2. If the tracer is not started, acpi_gbl_trace_method_name should be
|
||||
* matched if it is specified
|
||||
* 3. If the tracer is oneshot style, acpi_gbl_trace_method_name should
|
||||
* not be cleared by the trace stopper during the first match
|
||||
*/
|
||||
if (acpi_gbl_trace_method_object) {
|
||||
return (TRUE);
|
||||
}
|
||||
if (name &&
|
||||
(acpi_gbl_trace_method_name &&
|
||||
strcmp(acpi_gbl_trace_method_name, name))) {
|
||||
return (FALSE);
|
||||
}
|
||||
if ((acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) &&
|
||||
!acpi_gbl_trace_method_name) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_start_trace_method
|
||||
*
|
||||
* PARAMETERS: method_node - Node of the method
|
||||
* obj_desc - The method object
|
||||
* walk_state - current state, NULL if not yet executing
|
||||
* a method.
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Start control method execution trace
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_start_trace_method(struct acpi_namespace_node *method_node,
|
||||
union acpi_operand_object *obj_desc,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
acpi_status status;
|
||||
char *pathname = NULL;
|
||||
u8 enabled = FALSE;
|
||||
|
||||
ACPI_FUNCTION_NAME(ex_start_trace_method);
|
||||
|
||||
if (method_node) {
|
||||
pathname = acpi_ns_get_normalized_pathname(method_node, TRUE);
|
||||
}
|
||||
|
||||
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
enabled = acpi_ex_interpreter_trace_enabled(pathname);
|
||||
if (enabled && !acpi_gbl_trace_method_object) {
|
||||
acpi_gbl_trace_method_object = obj_desc;
|
||||
acpi_gbl_original_dbg_level = acpi_dbg_level;
|
||||
acpi_gbl_original_dbg_layer = acpi_dbg_layer;
|
||||
acpi_dbg_level = ACPI_TRACE_LEVEL_ALL;
|
||||
acpi_dbg_layer = ACPI_TRACE_LAYER_ALL;
|
||||
|
||||
if (acpi_gbl_trace_dbg_level) {
|
||||
acpi_dbg_level = acpi_gbl_trace_dbg_level;
|
||||
}
|
||||
if (acpi_gbl_trace_dbg_layer) {
|
||||
acpi_dbg_layer = acpi_gbl_trace_dbg_layer;
|
||||
}
|
||||
}
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
|
||||
exit:
|
||||
if (enabled) {
|
||||
if (pathname) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT,
|
||||
"Begin method [0x%p:%s] execution.\n",
|
||||
obj_desc->method.aml_start,
|
||||
pathname));
|
||||
} else {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT,
|
||||
"Begin method [0x%p] execution.\n",
|
||||
obj_desc->method.aml_start));
|
||||
}
|
||||
}
|
||||
if (pathname) {
|
||||
ACPI_FREE(pathname);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_stop_trace_method
|
||||
*
|
||||
* PARAMETERS: method_node - Node of the method
|
||||
* obj_desc - The method object
|
||||
* walk_state - current state, NULL if not yet executing
|
||||
* a method.
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Stop control method execution trace
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_stop_trace_method(struct acpi_namespace_node *method_node,
|
||||
union acpi_operand_object *obj_desc,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
acpi_status status;
|
||||
char *pathname = NULL;
|
||||
u8 enabled;
|
||||
|
||||
ACPI_FUNCTION_NAME(ex_stop_trace_method);
|
||||
|
||||
if (method_node) {
|
||||
pathname = acpi_ns_get_normalized_pathname(method_node, TRUE);
|
||||
}
|
||||
|
||||
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto exit_path;
|
||||
}
|
||||
|
||||
enabled = acpi_ex_interpreter_trace_enabled(NULL);
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
|
||||
if (enabled) {
|
||||
if (pathname) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT,
|
||||
"End method [0x%p:%s] execution.\n",
|
||||
obj_desc->method.aml_start,
|
||||
pathname));
|
||||
} else {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT,
|
||||
"End method [0x%p] execution.\n",
|
||||
obj_desc->method.aml_start));
|
||||
}
|
||||
}
|
||||
|
||||
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto exit_path;
|
||||
}
|
||||
|
||||
/* Check whether the tracer should be stopped */
|
||||
|
||||
if (acpi_gbl_trace_method_object == obj_desc) {
|
||||
|
||||
/* Disable further tracing if type is one-shot */
|
||||
|
||||
if (acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) {
|
||||
acpi_gbl_trace_method_name = NULL;
|
||||
}
|
||||
|
||||
acpi_dbg_level = acpi_gbl_original_dbg_level;
|
||||
acpi_dbg_layer = acpi_gbl_original_dbg_layer;
|
||||
acpi_gbl_trace_method_object = NULL;
|
||||
}
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
|
||||
exit_path:
|
||||
if (pathname) {
|
||||
ACPI_FREE(pathname);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_start_trace_opcode
|
||||
*
|
||||
* PARAMETERS: op - The parser opcode object
|
||||
* walk_state - current state, NULL if not yet executing
|
||||
* a method.
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Start opcode execution trace
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_start_trace_opcode(union acpi_parse_object *op,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
|
||||
ACPI_FUNCTION_NAME(ex_start_trace_opcode);
|
||||
|
||||
if (acpi_ex_interpreter_trace_enabled(NULL)) {
|
||||
if (walk_state->op_info) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT,
|
||||
"Begin opcode: %s[0x%p] Class=0x%02x, Type=0x%02x, Flags=0x%04x.\n",
|
||||
op->common.aml_op_name,
|
||||
op->common.aml,
|
||||
walk_state->op_info->class,
|
||||
walk_state->op_info->type,
|
||||
walk_state->op_info->flags));
|
||||
} else {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT,
|
||||
"Begin opcode: %s[0x%p].\n",
|
||||
op->common.aml_op_name,
|
||||
op->common.aml));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_stop_trace_opcode
|
||||
*
|
||||
* PARAMETERS: op - The parser opcode object
|
||||
* walk_state - current state, NULL if not yet executing
|
||||
* a method.
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Stop opcode execution trace
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_stop_trace_opcode(union acpi_parse_object *op,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
|
||||
ACPI_FUNCTION_NAME(ex_stop_trace_opcode);
|
||||
|
||||
if (acpi_ex_interpreter_trace_enabled(NULL)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT,
|
||||
"End opcode: %s[0x%p].\n",
|
||||
op->common.aml_op_name, op->common.aml));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user