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
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