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 - 2025, 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 [%s] execution.\n", 140 acpi_ex_get_trace_event_name(type), 141 begin ? "Begin" : "End", 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_trace_args 153 * 154 * PARAMETERS: params - AML method arguments 155 * count - numer of method arguments 156 * 157 * RETURN: None 158 * 159 * DESCRIPTION: Trace any arguments 160 * 161 ******************************************************************************/ 162 163 void 164 acpi_ex_trace_args(union acpi_operand_object **params, u32 count) 165 { 166 u32 i; 167 168 ACPI_FUNCTION_NAME(ex_trace_args); 169 170 for (i = 0; i < count; i++) { 171 union acpi_operand_object *obj_desc = params[i]; 172 173 if (!i) { 174 ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT, " ")); 175 } 176 177 switch (obj_desc->common.type) { 178 case ACPI_TYPE_INTEGER: 179 ACPI_DEBUG_PRINT_RAW((ACPI_DB_TRACE_POINT, "%llx", obj_desc->integer.value)); 180 break; 181 case ACPI_TYPE_STRING: 182 if (!obj_desc->string.length) { 183 ACPI_DEBUG_PRINT_RAW((ACPI_DB_TRACE_POINT, "NULL")); 184 continue; 185 } 186 if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_TRACE_POINT, _COMPONENT)) 187 acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX); 188 break; 189 default: 190 ACPI_DEBUG_PRINT_RAW((ACPI_DB_TRACE_POINT, "Unknown")); 191 break; 192 } 193 if (i+1 == count) { 194 ACPI_DEBUG_PRINT_RAW((ACPI_DB_TRACE_POINT, "\n")); 195 } else { 196 ACPI_DEBUG_PRINT_RAW((ACPI_DB_TRACE_POINT, ", ")); 197 } 198 } 199 } 200 201 /******************************************************************************* 202 * 203 * FUNCTION: acpi_ex_start_trace_method 204 * 205 * PARAMETERS: method_node - Node of the method 206 * obj_desc - The method object 207 * walk_state - current state, NULL if not yet executing 208 * a method. 209 * 210 * RETURN: None 211 * 212 * DESCRIPTION: Start control method execution trace 213 * 214 ******************************************************************************/ 215 216 void 217 acpi_ex_start_trace_method(struct acpi_namespace_node *method_node, 218 union acpi_operand_object *obj_desc, 219 struct acpi_walk_state *walk_state) 220 { 221 char *pathname = NULL; 222 u8 enabled = FALSE; 223 224 ACPI_FUNCTION_NAME(ex_start_trace_method); 225 226 if (method_node) { 227 pathname = acpi_ns_get_normalized_pathname(method_node, TRUE); 228 } 229 230 enabled = acpi_ex_interpreter_trace_enabled(pathname); 231 if (enabled && !acpi_gbl_trace_method_object) { 232 acpi_gbl_trace_method_object = obj_desc; 233 acpi_gbl_original_dbg_level = acpi_dbg_level; 234 acpi_gbl_original_dbg_layer = acpi_dbg_layer; 235 acpi_dbg_level = ACPI_TRACE_LEVEL_ALL; 236 acpi_dbg_layer = ACPI_TRACE_LAYER_ALL; 237 238 if (acpi_gbl_trace_dbg_level) { 239 acpi_dbg_level = acpi_gbl_trace_dbg_level; 240 } 241 242 if (acpi_gbl_trace_dbg_layer) { 243 acpi_dbg_layer = acpi_gbl_trace_dbg_layer; 244 } 245 } 246 247 if (enabled) { 248 ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, TRUE, 249 obj_desc ? obj_desc->method.aml_start : NULL, 250 pathname); 251 } 252 253 if (pathname) { 254 ACPI_FREE(pathname); 255 } 256 } 257 258 /******************************************************************************* 259 * 260 * FUNCTION: acpi_ex_stop_trace_method 261 * 262 * PARAMETERS: method_node - Node of the method 263 * obj_desc - The method object 264 * walk_state - current state, NULL if not yet executing 265 * a method. 266 * 267 * RETURN: None 268 * 269 * DESCRIPTION: Stop control method execution trace 270 * 271 ******************************************************************************/ 272 273 void 274 acpi_ex_stop_trace_method(struct acpi_namespace_node *method_node, 275 union acpi_operand_object *obj_desc, 276 struct acpi_walk_state *walk_state) 277 { 278 char *pathname = NULL; 279 u8 enabled; 280 281 ACPI_FUNCTION_NAME(ex_stop_trace_method); 282 283 if (method_node) { 284 pathname = acpi_ns_get_normalized_pathname(method_node, TRUE); 285 } 286 287 enabled = acpi_ex_interpreter_trace_enabled(NULL); 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 /* Check whether the tracer should be stopped */ 296 297 if (acpi_gbl_trace_method_object == obj_desc) { 298 299 /* Disable further tracing if type is one-shot */ 300 301 if (acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) { 302 acpi_gbl_trace_method_name = NULL; 303 } 304 305 acpi_dbg_level = acpi_gbl_original_dbg_level; 306 acpi_dbg_layer = acpi_gbl_original_dbg_layer; 307 acpi_gbl_trace_method_object = NULL; 308 } 309 310 if (pathname) { 311 ACPI_FREE(pathname); 312 } 313 } 314 315 /******************************************************************************* 316 * 317 * FUNCTION: acpi_ex_start_trace_opcode 318 * 319 * PARAMETERS: op - The parser opcode object 320 * walk_state - current state, NULL if not yet executing 321 * a method. 322 * 323 * RETURN: None 324 * 325 * DESCRIPTION: Start opcode execution trace 326 * 327 ******************************************************************************/ 328 329 void 330 acpi_ex_start_trace_opcode(union acpi_parse_object *op, 331 struct acpi_walk_state *walk_state) 332 { 333 334 ACPI_FUNCTION_NAME(ex_start_trace_opcode); 335 336 if (acpi_ex_interpreter_trace_enabled(NULL) && 337 (acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) { 338 ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, TRUE, 339 op->common.aml, op->common.aml_op_name); 340 } 341 } 342 343 /******************************************************************************* 344 * 345 * FUNCTION: acpi_ex_stop_trace_opcode 346 * 347 * PARAMETERS: op - The parser opcode object 348 * walk_state - current state, NULL if not yet executing 349 * a method. 350 * 351 * RETURN: None 352 * 353 * DESCRIPTION: Stop opcode execution trace 354 * 355 ******************************************************************************/ 356 357 void 358 acpi_ex_stop_trace_opcode(union acpi_parse_object *op, 359 struct acpi_walk_state *walk_state) 360 { 361 362 ACPI_FUNCTION_NAME(ex_stop_trace_opcode); 363 364 if (acpi_ex_interpreter_trace_enabled(NULL) && 365 (acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) { 366 ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, FALSE, 367 op->common.aml, op->common.aml_op_name); 368 } 369 } 370