1 /****************************************************************************** 2 * 3 * Module Name: extrace - Support for interpreter execution tracing 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2018, 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 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 256 void 257 acpi_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 312 void 313 acpi_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 340 void 341 acpi_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