1291333Sjkim/******************************************************************************
2291333Sjkim *
3291333Sjkim * Module Name: extrace - Support for interpreter execution tracing
4291333Sjkim *
5291333Sjkim *****************************************************************************/
6291333Sjkim
7291333Sjkim/*
8298714Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
9291333Sjkim * All rights reserved.
10291333Sjkim *
11291333Sjkim * Redistribution and use in source and binary forms, with or without
12291333Sjkim * modification, are permitted provided that the following conditions
13291333Sjkim * are met:
14291333Sjkim * 1. Redistributions of source code must retain the above copyright
15291333Sjkim *    notice, this list of conditions, and the following disclaimer,
16291333Sjkim *    without modification.
17291333Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18291333Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19291333Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20291333Sjkim *    including a substantially similar Disclaimer requirement for further
21291333Sjkim *    binary redistribution.
22291333Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23291333Sjkim *    of any contributors may be used to endorse or promote products derived
24291333Sjkim *    from this software without specific prior written permission.
25291333Sjkim *
26291333Sjkim * Alternatively, this software may be distributed under the terms of the
27291333Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28291333Sjkim * Software Foundation.
29291333Sjkim *
30291333Sjkim * NO WARRANTY
31291333Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32291333Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33291333Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34291333Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35291333Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36291333Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37291333Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38291333Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39291333Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40291333Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41291333Sjkim * POSSIBILITY OF SUCH DAMAGES.
42291333Sjkim */
43291333Sjkim
44298714Sjkim#include <contrib/dev/acpica/include/acpi.h>
45298714Sjkim#include <contrib/dev/acpica/include/accommon.h>
46298714Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
47298714Sjkim#include <contrib/dev/acpica/include/acinterp.h>
48291333Sjkim
49291333Sjkim
50291333Sjkim#define _COMPONENT          ACPI_EXECUTER
51291333Sjkim        ACPI_MODULE_NAME    ("extrace")
52291333Sjkim
53291333Sjkim
54291333Sjkimstatic ACPI_OPERAND_OBJECT  *AcpiGbl_TraceMethodObject = NULL;
55291333Sjkim
56291333Sjkim/* Local prototypes */
57291333Sjkim
58291333Sjkim#ifdef ACPI_DEBUG_OUTPUT
59291333Sjkimstatic const char *
60291333SjkimAcpiExGetTraceEventName (
61291333Sjkim    ACPI_TRACE_EVENT_TYPE   Type);
62291333Sjkim#endif
63291333Sjkim
64291333Sjkim
65291333Sjkim/*******************************************************************************
66291333Sjkim *
67291333Sjkim * FUNCTION:    AcpiExInterpreterTraceEnabled
68291333Sjkim *
69291333Sjkim * PARAMETERS:  Name                - Whether method name should be matched,
70291333Sjkim *                                    this should be checked before starting
71291333Sjkim *                                    the tracer
72291333Sjkim *
73291333Sjkim * RETURN:      TRUE if interpreter trace is enabled.
74291333Sjkim *
75291333Sjkim * DESCRIPTION: Check whether interpreter trace is enabled
76291333Sjkim *
77291333Sjkim ******************************************************************************/
78291333Sjkim
79291333Sjkimstatic BOOLEAN
80291333SjkimAcpiExInterpreterTraceEnabled (
81291333Sjkim    char                    *Name)
82291333Sjkim{
83291333Sjkim
84291333Sjkim    /* Check if tracing is enabled */
85291333Sjkim
86291333Sjkim    if (!(AcpiGbl_TraceFlags & ACPI_TRACE_ENABLED))
87291333Sjkim    {
88291333Sjkim        return (FALSE);
89291333Sjkim    }
90291333Sjkim
91291333Sjkim    /*
92291333Sjkim     * Check if tracing is filtered:
93291333Sjkim     *
94291333Sjkim     * 1. If the tracer is started, AcpiGbl_TraceMethodObject should have
95291333Sjkim     *    been filled by the trace starter
96291333Sjkim     * 2. If the tracer is not started, AcpiGbl_TraceMethodName should be
97291333Sjkim     *    matched if it is specified
98291333Sjkim     * 3. If the tracer is oneshot style, AcpiGbl_TraceMethodName should
99291333Sjkim     *    not be cleared by the trace stopper during the first match
100291333Sjkim     */
101291333Sjkim    if (AcpiGbl_TraceMethodObject)
102291333Sjkim    {
103291333Sjkim        return (TRUE);
104291333Sjkim    }
105291333Sjkim
106291333Sjkim    if (Name &&
107291333Sjkim        (AcpiGbl_TraceMethodName &&
108291333Sjkim         strcmp (AcpiGbl_TraceMethodName, Name)))
109291333Sjkim    {
110291333Sjkim        return (FALSE);
111291333Sjkim    }
112291333Sjkim
113291333Sjkim    if ((AcpiGbl_TraceFlags & ACPI_TRACE_ONESHOT) &&
114291333Sjkim        !AcpiGbl_TraceMethodName)
115291333Sjkim    {
116291333Sjkim        return (FALSE);
117291333Sjkim    }
118291333Sjkim
119291333Sjkim    return (TRUE);
120291333Sjkim}
121291333Sjkim
122291333Sjkim
123291333Sjkim/*******************************************************************************
124291333Sjkim *
125291333Sjkim * FUNCTION:    AcpiExGetTraceEventName
126291333Sjkim *
127291333Sjkim * PARAMETERS:  Type            - Trace event type
128291333Sjkim *
129291333Sjkim * RETURN:      Trace event name.
130291333Sjkim *
131291333Sjkim * DESCRIPTION: Used to obtain the full trace event name.
132291333Sjkim *
133291333Sjkim ******************************************************************************/
134291333Sjkim
135291333Sjkim#ifdef ACPI_DEBUG_OUTPUT
136291333Sjkim
137291333Sjkimstatic const char *
138291333SjkimAcpiExGetTraceEventName (
139291333Sjkim    ACPI_TRACE_EVENT_TYPE   Type)
140291333Sjkim{
141291333Sjkim
142291333Sjkim    switch (Type)
143291333Sjkim    {
144291333Sjkim    case ACPI_TRACE_AML_METHOD:
145291333Sjkim
146291333Sjkim        return "Method";
147291333Sjkim
148291333Sjkim    case ACPI_TRACE_AML_OPCODE:
149291333Sjkim
150291333Sjkim        return "Opcode";
151291333Sjkim
152291333Sjkim    case ACPI_TRACE_AML_REGION:
153291333Sjkim
154291333Sjkim        return "Region";
155291333Sjkim
156291333Sjkim    default:
157291333Sjkim
158291333Sjkim        return "";
159291333Sjkim    }
160291333Sjkim}
161291333Sjkim
162291333Sjkim#endif
163291333Sjkim
164291333Sjkim
165291333Sjkim/*******************************************************************************
166291333Sjkim *
167291333Sjkim * FUNCTION:    AcpiExTracePoint
168291333Sjkim *
169291333Sjkim * PARAMETERS:  Type                - Trace event type
170291333Sjkim *              Begin               - TRUE if before execution
171291333Sjkim *              Aml                 - Executed AML address
172291333Sjkim *              Pathname            - Object path
173291333Sjkim *
174291333Sjkim * RETURN:      None
175291333Sjkim *
176291333Sjkim * DESCRIPTION: Internal interpreter execution trace.
177291333Sjkim *
178291333Sjkim ******************************************************************************/
179291333Sjkim
180291333Sjkimvoid
181291333SjkimAcpiExTracePoint (
182291333Sjkim    ACPI_TRACE_EVENT_TYPE   Type,
183291333Sjkim    BOOLEAN                 Begin,
184291333Sjkim    UINT8                   *Aml,
185291333Sjkim    char                    *Pathname)
186291333Sjkim{
187291333Sjkim
188291333Sjkim    ACPI_FUNCTION_NAME (ExTracePoint);
189291333Sjkim
190291333Sjkim
191291333Sjkim    if (Pathname)
192291333Sjkim    {
193291333Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_TRACE_POINT,
194291333Sjkim            "%s %s [0x%p:%s] execution.\n",
195291333Sjkim            AcpiExGetTraceEventName (Type), Begin ? "Begin" : "End",
196291333Sjkim            Aml, Pathname));
197291333Sjkim    }
198291333Sjkim    else
199291333Sjkim    {
200291333Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_TRACE_POINT,
201291333Sjkim            "%s %s [0x%p] execution.\n",
202291333Sjkim            AcpiExGetTraceEventName (Type), Begin ? "Begin" : "End",
203291333Sjkim            Aml));
204291333Sjkim    }
205291333Sjkim}
206291333Sjkim
207291333Sjkim
208291333Sjkim/*******************************************************************************
209291333Sjkim *
210291333Sjkim * FUNCTION:    AcpiExStartTraceMethod
211291333Sjkim *
212291333Sjkim * PARAMETERS:  MethodNode          - Node of the method
213291333Sjkim *              ObjDesc             - The method object
214291333Sjkim *              WalkState           - current state, NULL if not yet executing
215291333Sjkim *                                    a method.
216291333Sjkim *
217291333Sjkim * RETURN:      None
218291333Sjkim *
219291333Sjkim * DESCRIPTION: Start control method execution trace
220291333Sjkim *
221291333Sjkim ******************************************************************************/
222291333Sjkim
223291333Sjkimvoid
224291333SjkimAcpiExStartTraceMethod (
225291333Sjkim    ACPI_NAMESPACE_NODE     *MethodNode,
226291333Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc,
227291333Sjkim    ACPI_WALK_STATE         *WalkState)
228291333Sjkim{
229291333Sjkim    ACPI_STATUS             Status;
230291333Sjkim    char                    *Pathname = NULL;
231291333Sjkim    BOOLEAN                 Enabled = FALSE;
232291333Sjkim
233291333Sjkim
234291333Sjkim    ACPI_FUNCTION_NAME (ExStartTraceMethod);
235291333Sjkim
236291333Sjkim
237291333Sjkim    if (MethodNode)
238291333Sjkim    {
239291333Sjkim        Pathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE);
240291333Sjkim    }
241291333Sjkim
242291333Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
243291333Sjkim    if (ACPI_FAILURE (Status))
244291333Sjkim    {
245291333Sjkim        goto Exit;
246291333Sjkim    }
247291333Sjkim
248291333Sjkim    Enabled = AcpiExInterpreterTraceEnabled (Pathname);
249291333Sjkim    if (Enabled && !AcpiGbl_TraceMethodObject)
250291333Sjkim    {
251291333Sjkim        AcpiGbl_TraceMethodObject = ObjDesc;
252291333Sjkim        AcpiGbl_OriginalDbgLevel = AcpiDbgLevel;
253291333Sjkim        AcpiGbl_OriginalDbgLayer = AcpiDbgLayer;
254291333Sjkim        AcpiDbgLevel = ACPI_TRACE_LEVEL_ALL;
255291333Sjkim        AcpiDbgLayer = ACPI_TRACE_LAYER_ALL;
256291333Sjkim
257291333Sjkim        if (AcpiGbl_TraceDbgLevel)
258291333Sjkim        {
259291333Sjkim            AcpiDbgLevel = AcpiGbl_TraceDbgLevel;
260291333Sjkim        }
261291333Sjkim
262291333Sjkim        if (AcpiGbl_TraceDbgLayer)
263291333Sjkim        {
264291333Sjkim            AcpiDbgLayer = AcpiGbl_TraceDbgLayer;
265291333Sjkim        }
266291333Sjkim    }
267291333Sjkim
268291333Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
269291333Sjkim
270291333SjkimExit:
271291333Sjkim    if (Enabled)
272291333Sjkim    {
273291333Sjkim        ACPI_TRACE_POINT (ACPI_TRACE_AML_METHOD, TRUE,
274291333Sjkim            ObjDesc ? ObjDesc->Method.AmlStart : NULL, Pathname);
275291333Sjkim    }
276291333Sjkim
277291333Sjkim    if (Pathname)
278291333Sjkim    {
279291333Sjkim        ACPI_FREE (Pathname);
280291333Sjkim    }
281291333Sjkim}
282291333Sjkim
283291333Sjkim
284291333Sjkim/*******************************************************************************
285291333Sjkim *
286291333Sjkim * FUNCTION:    AcpiExStopTraceMethod
287291333Sjkim *
288291333Sjkim * PARAMETERS:  MethodNode          - Node of the method
289291333Sjkim *              ObjDesc             - The method object
290291333Sjkim *              WalkState           - current state, NULL if not yet executing
291291333Sjkim *                                    a method.
292291333Sjkim *
293291333Sjkim * RETURN:      None
294291333Sjkim *
295291333Sjkim * DESCRIPTION: Stop control method execution trace
296291333Sjkim *
297291333Sjkim ******************************************************************************/
298291333Sjkim
299291333Sjkimvoid
300291333SjkimAcpiExStopTraceMethod (
301291333Sjkim    ACPI_NAMESPACE_NODE     *MethodNode,
302291333Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc,
303291333Sjkim    ACPI_WALK_STATE         *WalkState)
304291333Sjkim{
305291333Sjkim    ACPI_STATUS             Status;
306291333Sjkim    char                    *Pathname = NULL;
307291333Sjkim    BOOLEAN                 Enabled;
308291333Sjkim
309291333Sjkim
310291333Sjkim    ACPI_FUNCTION_NAME (ExStopTraceMethod);
311291333Sjkim
312291333Sjkim
313291333Sjkim    if (MethodNode)
314291333Sjkim    {
315291333Sjkim        Pathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE);
316291333Sjkim    }
317291333Sjkim
318291333Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
319291333Sjkim    if (ACPI_FAILURE (Status))
320291333Sjkim    {
321291333Sjkim        goto ExitPath;
322291333Sjkim    }
323291333Sjkim
324291333Sjkim    Enabled = AcpiExInterpreterTraceEnabled (NULL);
325291333Sjkim
326291333Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
327291333Sjkim
328291333Sjkim    if (Enabled)
329291333Sjkim    {
330291333Sjkim        ACPI_TRACE_POINT (ACPI_TRACE_AML_METHOD, FALSE,
331291333Sjkim            ObjDesc ? ObjDesc->Method.AmlStart : NULL, Pathname);
332291333Sjkim    }
333291333Sjkim
334291333Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
335291333Sjkim    if (ACPI_FAILURE (Status))
336291333Sjkim    {
337291333Sjkim        goto ExitPath;
338291333Sjkim    }
339291333Sjkim
340291333Sjkim    /* Check whether the tracer should be stopped */
341291333Sjkim
342291333Sjkim    if (AcpiGbl_TraceMethodObject == ObjDesc)
343291333Sjkim    {
344291333Sjkim        /* Disable further tracing if type is one-shot */
345291333Sjkim
346291333Sjkim        if (AcpiGbl_TraceFlags & ACPI_TRACE_ONESHOT)
347291333Sjkim        {
348291333Sjkim            AcpiGbl_TraceMethodName = NULL;
349291333Sjkim        }
350291333Sjkim
351291333Sjkim        AcpiDbgLevel = AcpiGbl_OriginalDbgLevel;
352291333Sjkim        AcpiDbgLayer = AcpiGbl_OriginalDbgLayer;
353291333Sjkim        AcpiGbl_TraceMethodObject = NULL;
354291333Sjkim    }
355291333Sjkim
356291333Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
357291333Sjkim
358291333SjkimExitPath:
359291333Sjkim    if (Pathname)
360291333Sjkim    {
361291333Sjkim        ACPI_FREE (Pathname);
362291333Sjkim    }
363291333Sjkim}
364291333Sjkim
365291333Sjkim
366291333Sjkim/*******************************************************************************
367291333Sjkim *
368291333Sjkim * FUNCTION:    AcpiExStartTraceOpcode
369291333Sjkim *
370291333Sjkim * PARAMETERS:  Op                  - The parser opcode object
371291333Sjkim *              WalkState           - current state, NULL if not yet executing
372291333Sjkim *                                    a method.
373291333Sjkim *
374291333Sjkim * RETURN:      None
375291333Sjkim *
376291333Sjkim * DESCRIPTION: Start opcode execution trace
377291333Sjkim *
378291333Sjkim ******************************************************************************/
379291333Sjkim
380291333Sjkimvoid
381291333SjkimAcpiExStartTraceOpcode (
382291333Sjkim    ACPI_PARSE_OBJECT       *Op,
383291333Sjkim    ACPI_WALK_STATE         *WalkState)
384291333Sjkim{
385291333Sjkim
386291333Sjkim    ACPI_FUNCTION_NAME (ExStartTraceOpcode);
387291333Sjkim
388291333Sjkim
389291333Sjkim    if (AcpiExInterpreterTraceEnabled (NULL) &&
390291333Sjkim        (AcpiGbl_TraceFlags & ACPI_TRACE_OPCODE))
391291333Sjkim    {
392291333Sjkim        ACPI_TRACE_POINT (ACPI_TRACE_AML_OPCODE, TRUE,
393291333Sjkim            Op->Common.Aml, Op->Common.AmlOpName);
394291333Sjkim    }
395291333Sjkim}
396291333Sjkim
397291333Sjkim
398291333Sjkim/*******************************************************************************
399291333Sjkim *
400291333Sjkim * FUNCTION:    AcpiExStopTraceOpcode
401291333Sjkim *
402291333Sjkim * PARAMETERS:  Op                  - The parser opcode object
403291333Sjkim *              WalkState           - current state, NULL if not yet executing
404291333Sjkim *                                    a method.
405291333Sjkim *
406291333Sjkim * RETURN:      None
407291333Sjkim *
408291333Sjkim * DESCRIPTION: Stop opcode execution trace
409291333Sjkim *
410291333Sjkim ******************************************************************************/
411291333Sjkim
412291333Sjkimvoid
413291333SjkimAcpiExStopTraceOpcode (
414291333Sjkim    ACPI_PARSE_OBJECT       *Op,
415291333Sjkim    ACPI_WALK_STATE         *WalkState)
416291333Sjkim{
417291333Sjkim
418291333Sjkim    ACPI_FUNCTION_NAME (ExStopTraceOpcode);
419291333Sjkim
420291333Sjkim
421291333Sjkim    if (AcpiExInterpreterTraceEnabled (NULL) &&
422291333Sjkim        (AcpiGbl_TraceFlags & ACPI_TRACE_OPCODE))
423291333Sjkim    {
424291333Sjkim        ACPI_TRACE_POINT (ACPI_TRACE_AML_OPCODE, FALSE,
425291333Sjkim            Op->Common.Aml, Op->Common.AmlOpName);
426291333Sjkim    }
427291333Sjkim}
428