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.h"
45 #include "accommon.h"
46 #include "acnamesp.h"
47 #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
AcpiExInterpreterTraceEnabled(char * Name)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 *
AcpiExGetTraceEventName(ACPI_TRACE_EVENT_TYPE Type)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
AcpiExTracePoint(ACPI_TRACE_EVENT_TYPE Type,BOOLEAN Begin,UINT8 * Aml,char * Pathname)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
AcpiExStartTraceMethod(ACPI_NAMESPACE_NODE * MethodNode,ACPI_OPERAND_OBJECT * ObjDesc,ACPI_WALK_STATE * WalkState)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
AcpiExStopTraceMethod(ACPI_NAMESPACE_NODE * MethodNode,ACPI_OPERAND_OBJECT * ObjDesc,ACPI_WALK_STATE * WalkState)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
AcpiExStartTraceOpcode(ACPI_PARSE_OBJECT * Op,ACPI_WALK_STATE * WalkState)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
AcpiExStopTraceOpcode(ACPI_PARSE_OBJECT * Op,ACPI_WALK_STATE * WalkState)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