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 <contrib/dev/acpica/include/acpi.h> 45 #include <contrib/dev/acpica/include/accommon.h> 46 #include <contrib/dev/acpica/include/acnamesp.h> 47 #include <contrib/dev/acpica/include/acinterp.h> 48 49 50 #define _COMPONENT ACPI_EXECUTER 51 ACPI_MODULE_NAME ("extrace") 52 53 54 static ACPI_OPERAND_OBJECT *AcpiGbl_TraceMethodObject = NULL; 55 56 /* Local prototypes */ 57 58 #ifdef ACPI_DEBUG_OUTPUT 59 static const char * 60 AcpiExGetTraceEventName ( 61 ACPI_TRACE_EVENT_TYPE Type); 62 #endif 63 64 65 /******************************************************************************* 66 * 67 * FUNCTION: AcpiExInterpreterTraceEnabled 68 * 69 * PARAMETERS: Name - Whether method name should be matched, 70 * this should be checked before starting 71 * the tracer 72 * 73 * RETURN: TRUE if interpreter trace is enabled. 74 * 75 * DESCRIPTION: Check whether interpreter trace is enabled 76 * 77 ******************************************************************************/ 78 79 static BOOLEAN 80 AcpiExInterpreterTraceEnabled ( 81 char *Name) 82 { 83 84 /* Check if tracing is enabled */ 85 86 if (!(AcpiGbl_TraceFlags & ACPI_TRACE_ENABLED)) 87 { 88 return (FALSE); 89 } 90 91 /* 92 * Check if tracing is filtered: 93 * 94 * 1. If the tracer is started, AcpiGbl_TraceMethodObject should have 95 * been filled by the trace starter 96 * 2. If the tracer is not started, AcpiGbl_TraceMethodName should be 97 * matched if it is specified 98 * 3. If the tracer is oneshot style, AcpiGbl_TraceMethodName should 99 * not be cleared by the trace stopper during the first match 100 */ 101 if (AcpiGbl_TraceMethodObject) 102 { 103 return (TRUE); 104 } 105 106 if (Name && 107 (AcpiGbl_TraceMethodName && 108 strcmp (AcpiGbl_TraceMethodName, Name))) 109 { 110 return (FALSE); 111 } 112 113 if ((AcpiGbl_TraceFlags & ACPI_TRACE_ONESHOT) && 114 !AcpiGbl_TraceMethodName) 115 { 116 return (FALSE); 117 } 118 119 return (TRUE); 120 } 121 122 123 /******************************************************************************* 124 * 125 * FUNCTION: AcpiExGetTraceEventName 126 * 127 * PARAMETERS: Type - Trace event type 128 * 129 * RETURN: Trace event name. 130 * 131 * DESCRIPTION: Used to obtain the full trace event name. 132 * 133 ******************************************************************************/ 134 135 #ifdef ACPI_DEBUG_OUTPUT 136 137 static const char * 138 AcpiExGetTraceEventName ( 139 ACPI_TRACE_EVENT_TYPE Type) 140 { 141 142 switch (Type) 143 { 144 case ACPI_TRACE_AML_METHOD: 145 146 return "Method"; 147 148 case ACPI_TRACE_AML_OPCODE: 149 150 return "Opcode"; 151 152 case ACPI_TRACE_AML_REGION: 153 154 return "Region"; 155 156 default: 157 158 return ""; 159 } 160 } 161 162 #endif 163 164 165 /******************************************************************************* 166 * 167 * FUNCTION: AcpiExTracePoint 168 * 169 * PARAMETERS: Type - Trace event type 170 * Begin - TRUE if before execution 171 * Aml - Executed AML address 172 * Pathname - Object path 173 * 174 * RETURN: None 175 * 176 * DESCRIPTION: Internal interpreter execution trace. 177 * 178 ******************************************************************************/ 179 180 void 181 AcpiExTracePoint ( 182 ACPI_TRACE_EVENT_TYPE Type, 183 BOOLEAN Begin, 184 UINT8 *Aml, 185 char *Pathname) 186 { 187 188 ACPI_FUNCTION_NAME (ExTracePoint); 189 190 191 if (Pathname) 192 { 193 ACPI_DEBUG_PRINT ((ACPI_DB_TRACE_POINT, 194 "%s %s [0x%p:%s] execution.\n", 195 AcpiExGetTraceEventName (Type), Begin ? "Begin" : "End", 196 Aml, Pathname)); 197 } 198 else 199 { 200 ACPI_DEBUG_PRINT ((ACPI_DB_TRACE_POINT, 201 "%s %s [0x%p] execution.\n", 202 AcpiExGetTraceEventName (Type), Begin ? "Begin" : "End", 203 Aml)); 204 } 205 } 206 207 208 /******************************************************************************* 209 * 210 * FUNCTION: AcpiExStartTraceMethod 211 * 212 * PARAMETERS: MethodNode - Node of the method 213 * ObjDesc - The method object 214 * WalkState - current state, NULL if not yet executing 215 * a method. 216 * 217 * RETURN: None 218 * 219 * DESCRIPTION: Start control method execution trace 220 * 221 ******************************************************************************/ 222 223 void 224 AcpiExStartTraceMethod ( 225 ACPI_NAMESPACE_NODE *MethodNode, 226 ACPI_OPERAND_OBJECT *ObjDesc, 227 ACPI_WALK_STATE *WalkState) 228 { 229 ACPI_STATUS Status; 230 char *Pathname = NULL; 231 BOOLEAN Enabled = FALSE; 232 233 234 ACPI_FUNCTION_NAME (ExStartTraceMethod); 235 236 237 if (MethodNode) 238 { 239 Pathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE); 240 } 241 242 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 243 if (ACPI_FAILURE (Status)) 244 { 245 goto Exit; 246 } 247 248 Enabled = AcpiExInterpreterTraceEnabled (Pathname); 249 if (Enabled && !AcpiGbl_TraceMethodObject) 250 { 251 AcpiGbl_TraceMethodObject = ObjDesc; 252 AcpiGbl_OriginalDbgLevel = AcpiDbgLevel; 253 AcpiGbl_OriginalDbgLayer = AcpiDbgLayer; 254 AcpiDbgLevel = ACPI_TRACE_LEVEL_ALL; 255 AcpiDbgLayer = ACPI_TRACE_LAYER_ALL; 256 257 if (AcpiGbl_TraceDbgLevel) 258 { 259 AcpiDbgLevel = AcpiGbl_TraceDbgLevel; 260 } 261 262 if (AcpiGbl_TraceDbgLayer) 263 { 264 AcpiDbgLayer = AcpiGbl_TraceDbgLayer; 265 } 266 } 267 268 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 269 270 Exit: 271 if (Enabled) 272 { 273 ACPI_TRACE_POINT (ACPI_TRACE_AML_METHOD, TRUE, 274 ObjDesc ? ObjDesc->Method.AmlStart : NULL, Pathname); 275 } 276 277 if (Pathname) 278 { 279 ACPI_FREE (Pathname); 280 } 281 } 282 283 284 /******************************************************************************* 285 * 286 * FUNCTION: AcpiExStopTraceMethod 287 * 288 * PARAMETERS: MethodNode - Node of the method 289 * ObjDesc - The method object 290 * WalkState - current state, NULL if not yet executing 291 * a method. 292 * 293 * RETURN: None 294 * 295 * DESCRIPTION: Stop control method execution trace 296 * 297 ******************************************************************************/ 298 299 void 300 AcpiExStopTraceMethod ( 301 ACPI_NAMESPACE_NODE *MethodNode, 302 ACPI_OPERAND_OBJECT *ObjDesc, 303 ACPI_WALK_STATE *WalkState) 304 { 305 ACPI_STATUS Status; 306 char *Pathname = NULL; 307 BOOLEAN Enabled; 308 309 310 ACPI_FUNCTION_NAME (ExStopTraceMethod); 311 312 313 if (MethodNode) 314 { 315 Pathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE); 316 } 317 318 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 319 if (ACPI_FAILURE (Status)) 320 { 321 goto ExitPath; 322 } 323 324 Enabled = AcpiExInterpreterTraceEnabled (NULL); 325 326 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 327 328 if (Enabled) 329 { 330 ACPI_TRACE_POINT (ACPI_TRACE_AML_METHOD, FALSE, 331 ObjDesc ? ObjDesc->Method.AmlStart : NULL, Pathname); 332 } 333 334 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 335 if (ACPI_FAILURE (Status)) 336 { 337 goto ExitPath; 338 } 339 340 /* Check whether the tracer should be stopped */ 341 342 if (AcpiGbl_TraceMethodObject == ObjDesc) 343 { 344 /* Disable further tracing if type is one-shot */ 345 346 if (AcpiGbl_TraceFlags & ACPI_TRACE_ONESHOT) 347 { 348 AcpiGbl_TraceMethodName = NULL; 349 } 350 351 AcpiDbgLevel = AcpiGbl_OriginalDbgLevel; 352 AcpiDbgLayer = AcpiGbl_OriginalDbgLayer; 353 AcpiGbl_TraceMethodObject = NULL; 354 } 355 356 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 357 358 ExitPath: 359 if (Pathname) 360 { 361 ACPI_FREE (Pathname); 362 } 363 } 364 365 366 /******************************************************************************* 367 * 368 * FUNCTION: AcpiExStartTraceOpcode 369 * 370 * PARAMETERS: Op - The parser opcode object 371 * WalkState - current state, NULL if not yet executing 372 * a method. 373 * 374 * RETURN: None 375 * 376 * DESCRIPTION: Start opcode execution trace 377 * 378 ******************************************************************************/ 379 380 void 381 AcpiExStartTraceOpcode ( 382 ACPI_PARSE_OBJECT *Op, 383 ACPI_WALK_STATE *WalkState) 384 { 385 386 ACPI_FUNCTION_NAME (ExStartTraceOpcode); 387 388 389 if (AcpiExInterpreterTraceEnabled (NULL) && 390 (AcpiGbl_TraceFlags & ACPI_TRACE_OPCODE)) 391 { 392 ACPI_TRACE_POINT (ACPI_TRACE_AML_OPCODE, TRUE, 393 Op->Common.Aml, Op->Common.AmlOpName); 394 } 395 } 396 397 398 /******************************************************************************* 399 * 400 * FUNCTION: AcpiExStopTraceOpcode 401 * 402 * PARAMETERS: Op - The parser opcode object 403 * WalkState - current state, NULL if not yet executing 404 * a method. 405 * 406 * RETURN: None 407 * 408 * DESCRIPTION: Stop opcode execution trace 409 * 410 ******************************************************************************/ 411 412 void 413 AcpiExStopTraceOpcode ( 414 ACPI_PARSE_OBJECT *Op, 415 ACPI_WALK_STATE *WalkState) 416 { 417 418 ACPI_FUNCTION_NAME (ExStopTraceOpcode); 419 420 421 if (AcpiExInterpreterTraceEnabled (NULL) && 422 (AcpiGbl_TraceFlags & ACPI_TRACE_OPCODE)) 423 { 424 ACPI_TRACE_POINT (ACPI_TRACE_AML_OPCODE, FALSE, 425 Op->Common.Aml, Op->Common.AmlOpName); 426 } 427 } 428