linux/drivers/acpi/acpica/extrace.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2/******************************************************************************
   3 *
   4 * Module Name: extrace - Support for interpreter execution tracing
   5 *
   6 * Copyright (C) 2000 - 2019, Intel Corp.
   7 *
   8 *****************************************************************************/
   9
  10#include <acpi/acpi.h>
  11#include "accommon.h"
  12#include "acnamesp.h"
  13#include "acinterp.h"
  14
  15#define _COMPONENT          ACPI_EXECUTER
  16ACPI_MODULE_NAME("extrace")
  17
  18static union acpi_operand_object *acpi_gbl_trace_method_object = NULL;
  19
  20/* Local prototypes */
  21
  22#ifdef ACPI_DEBUG_OUTPUT
  23static const char *acpi_ex_get_trace_event_name(acpi_trace_event_type type);
  24#endif
  25
  26/*******************************************************************************
  27 *
  28 * FUNCTION:    acpi_ex_interpreter_trace_enabled
  29 *
  30 * PARAMETERS:  name                - Whether method name should be matched,
  31 *                                    this should be checked before starting
  32 *                                    the tracer
  33 *
  34 * RETURN:      TRUE if interpreter trace is enabled.
  35 *
  36 * DESCRIPTION: Check whether interpreter trace is enabled
  37 *
  38 ******************************************************************************/
  39
  40static u8 acpi_ex_interpreter_trace_enabled(char *name)
  41{
  42
  43        /* Check if tracing is enabled */
  44
  45        if (!(acpi_gbl_trace_flags & ACPI_TRACE_ENABLED)) {
  46                return (FALSE);
  47        }
  48
  49        /*
  50         * Check if tracing is filtered:
  51         *
  52         * 1. If the tracer is started, acpi_gbl_trace_method_object should have
  53         *    been filled by the trace starter
  54         * 2. If the tracer is not started, acpi_gbl_trace_method_name should be
  55         *    matched if it is specified
  56         * 3. If the tracer is oneshot style, acpi_gbl_trace_method_name should
  57         *    not be cleared by the trace stopper during the first match
  58         */
  59        if (acpi_gbl_trace_method_object) {
  60                return (TRUE);
  61        }
  62
  63        if (name &&
  64            (acpi_gbl_trace_method_name &&
  65             strcmp(acpi_gbl_trace_method_name, name))) {
  66                return (FALSE);
  67        }
  68
  69        if ((acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) &&
  70            !acpi_gbl_trace_method_name) {
  71                return (FALSE);
  72        }
  73
  74        return (TRUE);
  75}
  76
  77/*******************************************************************************
  78 *
  79 * FUNCTION:    acpi_ex_get_trace_event_name
  80 *
  81 * PARAMETERS:  type            - Trace event type
  82 *
  83 * RETURN:      Trace event name.
  84 *
  85 * DESCRIPTION: Used to obtain the full trace event name.
  86 *
  87 ******************************************************************************/
  88
  89#ifdef ACPI_DEBUG_OUTPUT
  90
  91static const char *acpi_ex_get_trace_event_name(acpi_trace_event_type type)
  92{
  93
  94        switch (type) {
  95        case ACPI_TRACE_AML_METHOD:
  96
  97                return "Method";
  98
  99        case ACPI_TRACE_AML_OPCODE:
 100
 101                return "Opcode";
 102
 103        case ACPI_TRACE_AML_REGION:
 104
 105                return "Region";
 106
 107        default:
 108
 109                return "";
 110        }
 111}
 112
 113#endif
 114
 115/*******************************************************************************
 116 *
 117 * FUNCTION:    acpi_ex_trace_point
 118 *
 119 * PARAMETERS:  type                - Trace event type
 120 *              begin               - TRUE if before execution
 121 *              aml                 - Executed AML address
 122 *              pathname            - Object path
 123 *
 124 * RETURN:      None
 125 *
 126 * DESCRIPTION: Internal interpreter execution trace.
 127 *
 128 ******************************************************************************/
 129
 130void
 131acpi_ex_trace_point(acpi_trace_event_type type,
 132                    u8 begin, u8 *aml, char *pathname)
 133{
 134
 135        ACPI_FUNCTION_NAME(ex_trace_point);
 136
 137        if (pathname) {
 138                ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT,
 139                                  "%s %s [0x%p:%s] execution.\n",
 140                                  acpi_ex_get_trace_event_name(type),
 141                                  begin ? "Begin" : "End", aml, pathname));
 142        } else {
 143                ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT,
 144                                  "%s %s [0x%p] execution.\n",
 145                                  acpi_ex_get_trace_event_name(type),
 146                                  begin ? "Begin" : "End", aml));
 147        }
 148}
 149
 150/*******************************************************************************
 151 *
 152 * FUNCTION:    acpi_ex_start_trace_method
 153 *
 154 * PARAMETERS:  method_node         - Node of the method
 155 *              obj_desc            - The method object
 156 *              walk_state          - current state, NULL if not yet executing
 157 *                                    a method.
 158 *
 159 * RETURN:      None
 160 *
 161 * DESCRIPTION: Start control method execution trace
 162 *
 163 ******************************************************************************/
 164
 165void
 166acpi_ex_start_trace_method(struct acpi_namespace_node *method_node,
 167                           union acpi_operand_object *obj_desc,
 168                           struct acpi_walk_state *walk_state)
 169{
 170        char *pathname = NULL;
 171        u8 enabled = FALSE;
 172
 173        ACPI_FUNCTION_NAME(ex_start_trace_method);
 174
 175        if (method_node) {
 176                pathname = acpi_ns_get_normalized_pathname(method_node, TRUE);
 177        }
 178
 179        enabled = acpi_ex_interpreter_trace_enabled(pathname);
 180        if (enabled && !acpi_gbl_trace_method_object) {
 181                acpi_gbl_trace_method_object = obj_desc;
 182                acpi_gbl_original_dbg_level = acpi_dbg_level;
 183                acpi_gbl_original_dbg_layer = acpi_dbg_layer;
 184                acpi_dbg_level = ACPI_TRACE_LEVEL_ALL;
 185                acpi_dbg_layer = ACPI_TRACE_LAYER_ALL;
 186
 187                if (acpi_gbl_trace_dbg_level) {
 188                        acpi_dbg_level = acpi_gbl_trace_dbg_level;
 189                }
 190
 191                if (acpi_gbl_trace_dbg_layer) {
 192                        acpi_dbg_layer = acpi_gbl_trace_dbg_layer;
 193                }
 194        }
 195
 196        if (enabled) {
 197                ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, TRUE,
 198                                 obj_desc ? obj_desc->method.aml_start : NULL,
 199                                 pathname);
 200        }
 201
 202        if (pathname) {
 203                ACPI_FREE(pathname);
 204        }
 205}
 206
 207/*******************************************************************************
 208 *
 209 * FUNCTION:    acpi_ex_stop_trace_method
 210 *
 211 * PARAMETERS:  method_node         - Node of the method
 212 *              obj_desc            - The method object
 213 *              walk_state          - current state, NULL if not yet executing
 214 *                                    a method.
 215 *
 216 * RETURN:      None
 217 *
 218 * DESCRIPTION: Stop control method execution trace
 219 *
 220 ******************************************************************************/
 221
 222void
 223acpi_ex_stop_trace_method(struct acpi_namespace_node *method_node,
 224                          union acpi_operand_object *obj_desc,
 225                          struct acpi_walk_state *walk_state)
 226{
 227        char *pathname = NULL;
 228        u8 enabled;
 229
 230        ACPI_FUNCTION_NAME(ex_stop_trace_method);
 231
 232        if (method_node) {
 233                pathname = acpi_ns_get_normalized_pathname(method_node, TRUE);
 234        }
 235
 236        enabled = acpi_ex_interpreter_trace_enabled(NULL);
 237
 238        if (enabled) {
 239                ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, FALSE,
 240                                 obj_desc ? obj_desc->method.aml_start : NULL,
 241                                 pathname);
 242        }
 243
 244        /* Check whether the tracer should be stopped */
 245
 246        if (acpi_gbl_trace_method_object == obj_desc) {
 247
 248                /* Disable further tracing if type is one-shot */
 249
 250                if (acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) {
 251                        acpi_gbl_trace_method_name = NULL;
 252                }
 253
 254                acpi_dbg_level = acpi_gbl_original_dbg_level;
 255                acpi_dbg_layer = acpi_gbl_original_dbg_layer;
 256                acpi_gbl_trace_method_object = NULL;
 257        }
 258
 259        if (pathname) {
 260                ACPI_FREE(pathname);
 261        }
 262}
 263
 264/*******************************************************************************
 265 *
 266 * FUNCTION:    acpi_ex_start_trace_opcode
 267 *
 268 * PARAMETERS:  op                  - The parser opcode object
 269 *              walk_state          - current state, NULL if not yet executing
 270 *                                    a method.
 271 *
 272 * RETURN:      None
 273 *
 274 * DESCRIPTION: Start opcode execution trace
 275 *
 276 ******************************************************************************/
 277
 278void
 279acpi_ex_start_trace_opcode(union acpi_parse_object *op,
 280                           struct acpi_walk_state *walk_state)
 281{
 282
 283        ACPI_FUNCTION_NAME(ex_start_trace_opcode);
 284
 285        if (acpi_ex_interpreter_trace_enabled(NULL) &&
 286            (acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) {
 287                ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, TRUE,
 288                                 op->common.aml, op->common.aml_op_name);
 289        }
 290}
 291
 292/*******************************************************************************
 293 *
 294 * FUNCTION:    acpi_ex_stop_trace_opcode
 295 *
 296 * PARAMETERS:  op                  - The parser opcode object
 297 *              walk_state          - current state, NULL if not yet executing
 298 *                                    a method.
 299 *
 300 * RETURN:      None
 301 *
 302 * DESCRIPTION: Stop opcode execution trace
 303 *
 304 ******************************************************************************/
 305
 306void
 307acpi_ex_stop_trace_opcode(union acpi_parse_object *op,
 308                          struct acpi_walk_state *walk_state)
 309{
 310
 311        ACPI_FUNCTION_NAME(ex_stop_trace_opcode);
 312
 313        if (acpi_ex_interpreter_trace_enabled(NULL) &&
 314            (acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) {
 315                ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, FALSE,
 316                                 op->common.aml, op->common.aml_op_name);
 317        }
 318}
 319