linux/drivers/acpi/acpica/extrace.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Module Name: extrace - Support for interpreter execution tracing
   4 *
   5 *****************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2017, Intel Corp.
   9 * All rights reserved.
  10 *
  11 * Redistribution and use in source and binary forms, with or without
  12 * modification, are permitted provided that the following conditions
  13 * are met:
  14 * 1. Redistributions of source code must retain the above copyright
  15 *    notice, this list of conditions, and the following disclaimer,
  16 *    without modification.
  17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18 *    substantially similar to the "NO WARRANTY" disclaimer below
  19 *    ("Disclaimer") and any redistribution must be conditioned upon
  20 *    including a substantially similar Disclaimer requirement for further
  21 *    binary redistribution.
  22 * 3. Neither the names of the above-listed copyright holders nor the names
  23 *    of any contributors may be used to endorse or promote products derived
  24 *    from this software without specific prior written permission.
  25 *
  26 * Alternatively, this software may be distributed under the terms of the
  27 * GNU General Public License ("GPL") version 2 as published by the Free
  28 * Software Foundation.
  29 *
  30 * NO WARRANTY
  31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41 * POSSIBILITY OF SUCH DAMAGES.
  42 */
  43
  44#include <acpi/acpi.h>
  45#include "accommon.h"
  46#include "acnamesp.h"
  47#include "acinterp.h"
  48
  49#define _COMPONENT          ACPI_EXECUTER
  50ACPI_MODULE_NAME("extrace")
  51
  52static union acpi_operand_object *acpi_gbl_trace_method_object = NULL;
  53
  54/* Local prototypes */
  55
  56#ifdef ACPI_DEBUG_OUTPUT
  57static const char *acpi_ex_get_trace_event_name(acpi_trace_event_type type);
  58#endif
  59
  60/*******************************************************************************
  61 *
  62 * FUNCTION:    acpi_ex_interpreter_trace_enabled
  63 *
  64 * PARAMETERS:  name                - Whether method name should be matched,
  65 *                                    this should be checked before starting
  66 *                                    the tracer
  67 *
  68 * RETURN:      TRUE if interpreter trace is enabled.
  69 *
  70 * DESCRIPTION: Check whether interpreter trace is enabled
  71 *
  72 ******************************************************************************/
  73
  74static u8 acpi_ex_interpreter_trace_enabled(char *name)
  75{
  76
  77        /* Check if tracing is enabled */
  78
  79        if (!(acpi_gbl_trace_flags & ACPI_TRACE_ENABLED)) {
  80                return (FALSE);
  81        }
  82
  83        /*
  84         * Check if tracing is filtered:
  85         *
  86         * 1. If the tracer is started, acpi_gbl_trace_method_object should have
  87         *    been filled by the trace starter
  88         * 2. If the tracer is not started, acpi_gbl_trace_method_name should be
  89         *    matched if it is specified
  90         * 3. If the tracer is oneshot style, acpi_gbl_trace_method_name should
  91         *    not be cleared by the trace stopper during the first match
  92         */
  93        if (acpi_gbl_trace_method_object) {
  94                return (TRUE);
  95        }
  96
  97        if (name &&
  98            (acpi_gbl_trace_method_name &&
  99             strcmp(acpi_gbl_trace_method_name, name))) {
 100                return (FALSE);
 101        }
 102
 103        if ((acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) &&
 104            !acpi_gbl_trace_method_name) {
 105                return (FALSE);
 106        }
 107
 108        return (TRUE);
 109}
 110
 111/*******************************************************************************
 112 *
 113 * FUNCTION:    acpi_ex_get_trace_event_name
 114 *
 115 * PARAMETERS:  type            - Trace event type
 116 *
 117 * RETURN:      Trace event name.
 118 *
 119 * DESCRIPTION: Used to obtain the full trace event name.
 120 *
 121 ******************************************************************************/
 122
 123#ifdef ACPI_DEBUG_OUTPUT
 124
 125static const char *acpi_ex_get_trace_event_name(acpi_trace_event_type type)
 126{
 127
 128        switch (type) {
 129        case ACPI_TRACE_AML_METHOD:
 130
 131                return "Method";
 132
 133        case ACPI_TRACE_AML_OPCODE:
 134
 135                return "Opcode";
 136
 137        case ACPI_TRACE_AML_REGION:
 138
 139                return "Region";
 140
 141        default:
 142
 143                return "";
 144        }
 145}
 146
 147#endif
 148
 149/*******************************************************************************
 150 *
 151 * FUNCTION:    acpi_ex_trace_point
 152 *
 153 * PARAMETERS:  type                - Trace event type
 154 *              begin               - TRUE if before execution
 155 *              aml                 - Executed AML address
 156 *              pathname            - Object path
 157 *
 158 * RETURN:      None
 159 *
 160 * DESCRIPTION: Internal interpreter execution trace.
 161 *
 162 ******************************************************************************/
 163
 164void
 165acpi_ex_trace_point(acpi_trace_event_type type,
 166                    u8 begin, u8 *aml, char *pathname)
 167{
 168
 169        ACPI_FUNCTION_NAME(ex_trace_point);
 170
 171        if (pathname) {
 172                ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT,
 173                                  "%s %s [0x%p:%s] execution.\n",
 174                                  acpi_ex_get_trace_event_name(type),
 175                                  begin ? "Begin" : "End", aml, pathname));
 176        } else {
 177                ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT,
 178                                  "%s %s [0x%p] execution.\n",
 179                                  acpi_ex_get_trace_event_name(type),
 180                                  begin ? "Begin" : "End", aml));
 181        }
 182}
 183
 184/*******************************************************************************
 185 *
 186 * FUNCTION:    acpi_ex_start_trace_method
 187 *
 188 * PARAMETERS:  method_node         - Node of the method
 189 *              obj_desc            - The method object
 190 *              walk_state          - current state, NULL if not yet executing
 191 *                                    a method.
 192 *
 193 * RETURN:      None
 194 *
 195 * DESCRIPTION: Start control method execution trace
 196 *
 197 ******************************************************************************/
 198
 199void
 200acpi_ex_start_trace_method(struct acpi_namespace_node *method_node,
 201                           union acpi_operand_object *obj_desc,
 202                           struct acpi_walk_state *walk_state)
 203{
 204        char *pathname = NULL;
 205        u8 enabled = FALSE;
 206
 207        ACPI_FUNCTION_NAME(ex_start_trace_method);
 208
 209        if (method_node) {
 210                pathname = acpi_ns_get_normalized_pathname(method_node, TRUE);
 211        }
 212
 213        enabled = acpi_ex_interpreter_trace_enabled(pathname);
 214        if (enabled && !acpi_gbl_trace_method_object) {
 215                acpi_gbl_trace_method_object = obj_desc;
 216                acpi_gbl_original_dbg_level = acpi_dbg_level;
 217                acpi_gbl_original_dbg_layer = acpi_dbg_layer;
 218                acpi_dbg_level = ACPI_TRACE_LEVEL_ALL;
 219                acpi_dbg_layer = ACPI_TRACE_LAYER_ALL;
 220
 221                if (acpi_gbl_trace_dbg_level) {
 222                        acpi_dbg_level = acpi_gbl_trace_dbg_level;
 223                }
 224
 225                if (acpi_gbl_trace_dbg_layer) {
 226                        acpi_dbg_layer = acpi_gbl_trace_dbg_layer;
 227                }
 228        }
 229
 230        if (enabled) {
 231                ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, TRUE,
 232                                 obj_desc ? obj_desc->method.aml_start : NULL,
 233                                 pathname);
 234        }
 235
 236        if (pathname) {
 237                ACPI_FREE(pathname);
 238        }
 239}
 240
 241/*******************************************************************************
 242 *
 243 * FUNCTION:    acpi_ex_stop_trace_method
 244 *
 245 * PARAMETERS:  method_node         - Node of the method
 246 *              obj_desc            - The method object
 247 *              walk_state          - current state, NULL if not yet executing
 248 *                                    a method.
 249 *
 250 * RETURN:      None
 251 *
 252 * DESCRIPTION: Stop control method execution trace
 253 *
 254 ******************************************************************************/
 255
 256void
 257acpi_ex_stop_trace_method(struct acpi_namespace_node *method_node,
 258                          union acpi_operand_object *obj_desc,
 259                          struct acpi_walk_state *walk_state)
 260{
 261        char *pathname = NULL;
 262        u8 enabled;
 263
 264        ACPI_FUNCTION_NAME(ex_stop_trace_method);
 265
 266        if (method_node) {
 267                pathname = acpi_ns_get_normalized_pathname(method_node, TRUE);
 268        }
 269
 270        enabled = acpi_ex_interpreter_trace_enabled(NULL);
 271
 272        if (enabled) {
 273                ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, FALSE,
 274                                 obj_desc ? obj_desc->method.aml_start : NULL,
 275                                 pathname);
 276        }
 277
 278        /* Check whether the tracer should be stopped */
 279
 280        if (acpi_gbl_trace_method_object == obj_desc) {
 281
 282                /* Disable further tracing if type is one-shot */
 283
 284                if (acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) {
 285                        acpi_gbl_trace_method_name = NULL;
 286                }
 287
 288                acpi_dbg_level = acpi_gbl_original_dbg_level;
 289                acpi_dbg_layer = acpi_gbl_original_dbg_layer;
 290                acpi_gbl_trace_method_object = NULL;
 291        }
 292
 293        if (pathname) {
 294                ACPI_FREE(pathname);
 295        }
 296}
 297
 298/*******************************************************************************
 299 *
 300 * FUNCTION:    acpi_ex_start_trace_opcode
 301 *
 302 * PARAMETERS:  op                  - The parser opcode object
 303 *              walk_state          - current state, NULL if not yet executing
 304 *                                    a method.
 305 *
 306 * RETURN:      None
 307 *
 308 * DESCRIPTION: Start opcode execution trace
 309 *
 310 ******************************************************************************/
 311
 312void
 313acpi_ex_start_trace_opcode(union acpi_parse_object *op,
 314                           struct acpi_walk_state *walk_state)
 315{
 316
 317        ACPI_FUNCTION_NAME(ex_start_trace_opcode);
 318
 319        if (acpi_ex_interpreter_trace_enabled(NULL) &&
 320            (acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) {
 321                ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, TRUE,
 322                                 op->common.aml, op->common.aml_op_name);
 323        }
 324}
 325
 326/*******************************************************************************
 327 *
 328 * FUNCTION:    acpi_ex_stop_trace_opcode
 329 *
 330 * PARAMETERS:  op                  - The parser opcode object
 331 *              walk_state          - current state, NULL if not yet executing
 332 *                                    a method.
 333 *
 334 * RETURN:      None
 335 *
 336 * DESCRIPTION: Stop opcode execution trace
 337 *
 338 ******************************************************************************/
 339
 340void
 341acpi_ex_stop_trace_opcode(union acpi_parse_object *op,
 342                          struct acpi_walk_state *walk_state)
 343{
 344
 345        ACPI_FUNCTION_NAME(ex_stop_trace_opcode);
 346
 347        if (acpi_ex_interpreter_trace_enabled(NULL) &&
 348            (acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) {
 349                ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, FALSE,
 350                                 op->common.aml, op->common.aml_op_name);
 351        }
 352}
 353