extrace.c revision 306536
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
54static ACPI_OPERAND_OBJECT  *AcpiGbl_TraceMethodObject = NULL;
55
56/* Local prototypes */
57
58#ifdef ACPI_DEBUG_OUTPUT
59static const char *
60AcpiExGetTraceEventName (
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
79static BOOLEAN
80AcpiExInterpreterTraceEnabled (
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
137static const char *
138AcpiExGetTraceEventName (
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
180void
181AcpiExTracePoint (
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
223void
224AcpiExStartTraceMethod (
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
270Exit:
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
299void
300AcpiExStopTraceMethod (
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
358ExitPath:
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
380void
381AcpiExStartTraceOpcode (
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
412void
413AcpiExStopTraceOpcode (
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