1 /****************************************************************************** 2 * 3 * Module Name: extrace - Support for interpreter execution tracing 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 50 ACPI_MODULE_NAME("extrace") 51 52 static union acpi_operand_object *acpi_gbl_trace_method_object = NULL; 53 54 /* Local prototypes */ 55 56 #ifdef ACPI_DEBUG_OUTPUT 57 static 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 74 static 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 125 static 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 164 void 165 acpi_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 199 void 200 acpi_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 acpi_status status; 205 char *pathname = NULL; 206 u8 enabled = FALSE; 207 208 ACPI_FUNCTION_NAME(ex_start_trace_method); 209 210 if (method_node) { 211 pathname = acpi_ns_get_normalized_pathname(method_node, TRUE); 212 } 213 214 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 215 if (ACPI_FAILURE(status)) { 216 goto exit; 217 } 218 219 enabled = acpi_ex_interpreter_trace_enabled(pathname); 220 if (enabled && !acpi_gbl_trace_method_object) { 221 acpi_gbl_trace_method_object = obj_desc; 222 acpi_gbl_original_dbg_level = acpi_dbg_level; 223 acpi_gbl_original_dbg_layer = acpi_dbg_layer; 224 acpi_dbg_level = ACPI_TRACE_LEVEL_ALL; 225 acpi_dbg_layer = ACPI_TRACE_LAYER_ALL; 226 227 if (acpi_gbl_trace_dbg_level) { 228 acpi_dbg_level = acpi_gbl_trace_dbg_level; 229 } 230 231 if (acpi_gbl_trace_dbg_layer) { 232 acpi_dbg_layer = acpi_gbl_trace_dbg_layer; 233 } 234 } 235 236 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 237 238 exit: 239 if (enabled) { 240 ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, TRUE, 241 obj_desc ? obj_desc->method.aml_start : NULL, 242 pathname); 243 } 244 245 if (pathname) { 246 ACPI_FREE(pathname); 247 } 248 } 249 250 /******************************************************************************* 251 * 252 * FUNCTION: acpi_ex_stop_trace_method 253 * 254 * PARAMETERS: method_node - Node of the method 255 * obj_desc - The method object 256 * walk_state - current state, NULL if not yet executing 257 * a method. 258 * 259 * RETURN: None 260 * 261 * DESCRIPTION: Stop control method execution trace 262 * 263 ******************************************************************************/ 264 265 void 266 acpi_ex_stop_trace_method(struct acpi_namespace_node *method_node, 267 union acpi_operand_object *obj_desc, 268 struct acpi_walk_state *walk_state) 269 { 270 acpi_status status; 271 char *pathname = NULL; 272 u8 enabled; 273 274 ACPI_FUNCTION_NAME(ex_stop_trace_method); 275 276 if (method_node) { 277 pathname = acpi_ns_get_normalized_pathname(method_node, TRUE); 278 } 279 280 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 281 if (ACPI_FAILURE(status)) { 282 goto exit_path; 283 } 284 285 enabled = acpi_ex_interpreter_trace_enabled(NULL); 286 287 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 288 289 if (enabled) { 290 ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, FALSE, 291 obj_desc ? obj_desc->method.aml_start : NULL, 292 pathname); 293 } 294 295 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 296 if (ACPI_FAILURE(status)) { 297 goto exit_path; 298 } 299 300 /* Check whether the tracer should be stopped */ 301 302 if (acpi_gbl_trace_method_object == obj_desc) { 303 304 /* Disable further tracing if type is one-shot */ 305 306 if (acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) { 307 acpi_gbl_trace_method_name = NULL; 308 } 309 310 acpi_dbg_level = acpi_gbl_original_dbg_level; 311 acpi_dbg_layer = acpi_gbl_original_dbg_layer; 312 acpi_gbl_trace_method_object = NULL; 313 } 314 315 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 316 317 exit_path: 318 if (pathname) { 319 ACPI_FREE(pathname); 320 } 321 } 322 323 /******************************************************************************* 324 * 325 * FUNCTION: acpi_ex_start_trace_opcode 326 * 327 * PARAMETERS: op - The parser opcode object 328 * walk_state - current state, NULL if not yet executing 329 * a method. 330 * 331 * RETURN: None 332 * 333 * DESCRIPTION: Start opcode execution trace 334 * 335 ******************************************************************************/ 336 337 void 338 acpi_ex_start_trace_opcode(union acpi_parse_object *op, 339 struct acpi_walk_state *walk_state) 340 { 341 342 ACPI_FUNCTION_NAME(ex_start_trace_opcode); 343 344 if (acpi_ex_interpreter_trace_enabled(NULL) && 345 (acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) { 346 ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, TRUE, 347 op->common.aml, op->common.aml_op_name); 348 } 349 } 350 351 /******************************************************************************* 352 * 353 * FUNCTION: acpi_ex_stop_trace_opcode 354 * 355 * PARAMETERS: op - The parser opcode object 356 * walk_state - current state, NULL if not yet executing 357 * a method. 358 * 359 * RETURN: None 360 * 361 * DESCRIPTION: Stop opcode execution trace 362 * 363 ******************************************************************************/ 364 365 void 366 acpi_ex_stop_trace_opcode(union acpi_parse_object *op, 367 struct acpi_walk_state *walk_state) 368 { 369 370 ACPI_FUNCTION_NAME(ex_stop_trace_opcode); 371 372 if (acpi_ex_interpreter_trace_enabled(NULL) && 373 (acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) { 374 ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, FALSE, 375 op->common.aml, op->common.aml_op_name); 376 } 377 } 378