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 - 2022, 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 16 ACPI_MODULE_NAME("extrace") 17 18 static union acpi_operand_object *acpi_gbl_trace_method_object = NULL; 19 20 /* Local prototypes */ 21 22 #ifdef ACPI_DEBUG_OUTPUT 23 static 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 40 static 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 91 static 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 130 void 131 acpi_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 165 void 166 acpi_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 222 void 223 acpi_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 278 void 279 acpi_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 306 void 307 acpi_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