1 /******************************************************************************
2  *
3  * Module Name: extrace - Support for interpreter execution tracing
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2020, 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     char                    *Pathname = NULL;
230     BOOLEAN                 Enabled = FALSE;
231 
232 
233     ACPI_FUNCTION_NAME (ExStartTraceMethod);
234 
235 
236     if (MethodNode)
237     {
238         Pathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE);
239     }
240 
241     Enabled = AcpiExInterpreterTraceEnabled (Pathname);
242     if (Enabled && !AcpiGbl_TraceMethodObject)
243     {
244         AcpiGbl_TraceMethodObject = ObjDesc;
245         AcpiGbl_OriginalDbgLevel = AcpiDbgLevel;
246         AcpiGbl_OriginalDbgLayer = AcpiDbgLayer;
247         AcpiDbgLevel = ACPI_TRACE_LEVEL_ALL;
248         AcpiDbgLayer = ACPI_TRACE_LAYER_ALL;
249 
250         if (AcpiGbl_TraceDbgLevel)
251         {
252             AcpiDbgLevel = AcpiGbl_TraceDbgLevel;
253         }
254 
255         if (AcpiGbl_TraceDbgLayer)
256         {
257             AcpiDbgLayer = AcpiGbl_TraceDbgLayer;
258         }
259     }
260 
261     if (Enabled)
262     {
263         ACPI_TRACE_POINT (ACPI_TRACE_AML_METHOD, TRUE,
264             ObjDesc ? ObjDesc->Method.AmlStart : NULL, Pathname);
265     }
266 
267     if (Pathname)
268     {
269         ACPI_FREE (Pathname);
270     }
271 }
272 
273 
274 /*******************************************************************************
275  *
276  * FUNCTION:    AcpiExStopTraceMethod
277  *
278  * PARAMETERS:  MethodNode          - Node of the method
279  *              ObjDesc             - The method object
280  *              WalkState           - current state, NULL if not yet executing
281  *                                    a method.
282  *
283  * RETURN:      None
284  *
285  * DESCRIPTION: Stop control method execution trace
286  *
287  ******************************************************************************/
288 
289 void
290 AcpiExStopTraceMethod (
291     ACPI_NAMESPACE_NODE     *MethodNode,
292     ACPI_OPERAND_OBJECT     *ObjDesc,
293     ACPI_WALK_STATE         *WalkState)
294 {
295     char                    *Pathname = NULL;
296     BOOLEAN                 Enabled;
297 
298 
299     ACPI_FUNCTION_NAME (ExStopTraceMethod);
300 
301 
302     if (MethodNode)
303     {
304         Pathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE);
305     }
306 
307     Enabled = AcpiExInterpreterTraceEnabled (NULL);
308 
309     if (Enabled)
310     {
311         ACPI_TRACE_POINT (ACPI_TRACE_AML_METHOD, FALSE,
312             ObjDesc ? ObjDesc->Method.AmlStart : NULL, Pathname);
313     }
314 
315     /* Check whether the tracer should be stopped */
316 
317     if (AcpiGbl_TraceMethodObject == ObjDesc)
318     {
319         /* Disable further tracing if type is one-shot */
320 
321         if (AcpiGbl_TraceFlags & ACPI_TRACE_ONESHOT)
322         {
323             AcpiGbl_TraceMethodName = NULL;
324         }
325 
326         AcpiDbgLevel = AcpiGbl_OriginalDbgLevel;
327         AcpiDbgLayer = AcpiGbl_OriginalDbgLayer;
328         AcpiGbl_TraceMethodObject = NULL;
329     }
330 
331     if (Pathname)
332     {
333         ACPI_FREE (Pathname);
334     }
335 }
336 
337 
338 /*******************************************************************************
339  *
340  * FUNCTION:    AcpiExStartTraceOpcode
341  *
342  * PARAMETERS:  Op                  - The parser opcode object
343  *              WalkState           - current state, NULL if not yet executing
344  *                                    a method.
345  *
346  * RETURN:      None
347  *
348  * DESCRIPTION: Start opcode execution trace
349  *
350  ******************************************************************************/
351 
352 void
353 AcpiExStartTraceOpcode (
354     ACPI_PARSE_OBJECT       *Op,
355     ACPI_WALK_STATE         *WalkState)
356 {
357 
358     ACPI_FUNCTION_NAME (ExStartTraceOpcode);
359 
360 
361     if (AcpiExInterpreterTraceEnabled (NULL) &&
362         (AcpiGbl_TraceFlags & ACPI_TRACE_OPCODE))
363     {
364         ACPI_TRACE_POINT (ACPI_TRACE_AML_OPCODE, TRUE,
365             Op->Common.Aml, Op->Common.AmlOpName);
366     }
367 }
368 
369 
370 /*******************************************************************************
371  *
372  * FUNCTION:    AcpiExStopTraceOpcode
373  *
374  * PARAMETERS:  Op                  - The parser opcode object
375  *              WalkState           - current state, NULL if not yet executing
376  *                                    a method.
377  *
378  * RETURN:      None
379  *
380  * DESCRIPTION: Stop opcode execution trace
381  *
382  ******************************************************************************/
383 
384 void
385 AcpiExStopTraceOpcode (
386     ACPI_PARSE_OBJECT       *Op,
387     ACPI_WALK_STATE         *WalkState)
388 {
389 
390     ACPI_FUNCTION_NAME (ExStopTraceOpcode);
391 
392 
393     if (AcpiExInterpreterTraceEnabled (NULL) &&
394         (AcpiGbl_TraceFlags & ACPI_TRACE_OPCODE))
395     {
396         ACPI_TRACE_POINT (ACPI_TRACE_AML_OPCODE, FALSE,
397             Op->Common.Aml, Op->Common.AmlOpName);
398     }
399 }
400