xref: /freebsd/sys/contrib/dev/acpica/components/executer/exdebug.c (revision f4b37ed0f8b307b1f3f0f630ca725d68f1dff30d)
1 /******************************************************************************
2  *
3  * Module Name: exdebug - Support for stores to the AML Debug Object
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, 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 #include <contrib/dev/acpica/include/acparser.h>
49 
50 
51 #define _COMPONENT          ACPI_EXECUTER
52         ACPI_MODULE_NAME    ("exdebug")
53 
54 
55 static ACPI_OPERAND_OBJECT  *AcpiGbl_TraceMethodObject = NULL;
56 
57 /* Local prototypes */
58 
59 #ifdef ACPI_DEBUG_OUTPUT
60 static const char *
61 AcpiExGetTraceEventName (
62     ACPI_TRACE_EVENT_TYPE   Type);
63 #endif
64 
65 
66 #ifndef ACPI_NO_ERROR_MESSAGES
67 /*******************************************************************************
68  *
69  * FUNCTION:    AcpiExDoDebugObject
70  *
71  * PARAMETERS:  SourceDesc          - Object to be output to "Debug Object"
72  *              Level               - Indentation level (used for packages)
73  *              Index               - Current package element, zero if not pkg
74  *
75  * RETURN:      None
76  *
77  * DESCRIPTION: Handles stores to the AML Debug Object. For example:
78  *              Store(INT1, Debug)
79  *
80  * This function is not compiled if ACPI_NO_ERROR_MESSAGES is set.
81  *
82  * This function is only enabled if AcpiGbl_EnableAmlDebugObject is set, or
83  * if ACPI_LV_DEBUG_OBJECT is set in the AcpiDbgLevel. Thus, in the normal
84  * operational case, stores to the debug object are ignored but can be easily
85  * enabled if necessary.
86  *
87  ******************************************************************************/
88 
89 void
90 AcpiExDoDebugObject (
91     ACPI_OPERAND_OBJECT     *SourceDesc,
92     UINT32                  Level,
93     UINT32                  Index)
94 {
95     UINT32                  i;
96     UINT32                  Timer;
97     ACPI_OPERAND_OBJECT     *ObjectDesc;
98     UINT32                  Value;
99 
100 
101     ACPI_FUNCTION_TRACE_PTR (ExDoDebugObject, SourceDesc);
102 
103 
104     /* Output must be enabled via the DebugObject global or the DbgLevel */
105 
106     if (!AcpiGbl_EnableAmlDebugObject &&
107         !(AcpiDbgLevel & ACPI_LV_DEBUG_OBJECT))
108     {
109         return_VOID;
110     }
111 
112     /*
113      * We will emit the current timer value (in microseconds) with each
114      * debug output. Only need the lower 26 bits. This allows for 67
115      * million microseconds or 67 seconds before rollover.
116      */
117     Timer = ((UINT32) AcpiOsGetTimer () / 10); /* (100 nanoseconds to microseconds) */
118     Timer &= 0x03FFFFFF;
119 
120     /*
121      * Print line header as long as we are not in the middle of an
122      * object display
123      */
124     if (!((Level > 0) && Index == 0))
125     {
126         AcpiOsPrintf ("[ACPI Debug %.8u] %*s", Timer, Level, " ");
127     }
128 
129     /* Display the index for package output only */
130 
131     if (Index > 0)
132     {
133        AcpiOsPrintf ("(%.2u) ", Index-1);
134     }
135 
136     if (!SourceDesc)
137     {
138         AcpiOsPrintf ("[Null Object]\n");
139         return_VOID;
140     }
141 
142     if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_OPERAND)
143     {
144         AcpiOsPrintf ("%s ", AcpiUtGetObjectTypeName (SourceDesc));
145 
146         if (!AcpiUtValidInternalObject (SourceDesc))
147         {
148            AcpiOsPrintf ("%p, Invalid Internal Object!\n", SourceDesc);
149            return_VOID;
150         }
151     }
152     else if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_NAMED)
153     {
154         AcpiOsPrintf ("%s: %p\n",
155             AcpiUtGetTypeName (((ACPI_NAMESPACE_NODE *) SourceDesc)->Type),
156             SourceDesc);
157         return_VOID;
158     }
159     else
160     {
161         return_VOID;
162     }
163 
164     /* SourceDesc is of type ACPI_DESC_TYPE_OPERAND */
165 
166     switch (SourceDesc->Common.Type)
167     {
168     case ACPI_TYPE_INTEGER:
169 
170         /* Output correct integer width */
171 
172         if (AcpiGbl_IntegerByteWidth == 4)
173         {
174             AcpiOsPrintf ("0x%8.8X\n",
175                 (UINT32) SourceDesc->Integer.Value);
176         }
177         else
178         {
179             AcpiOsPrintf ("0x%8.8X%8.8X\n",
180                 ACPI_FORMAT_UINT64 (SourceDesc->Integer.Value));
181         }
182         break;
183 
184     case ACPI_TYPE_BUFFER:
185 
186         AcpiOsPrintf ("[0x%.2X]\n", (UINT32) SourceDesc->Buffer.Length);
187         AcpiUtDumpBuffer (SourceDesc->Buffer.Pointer,
188             (SourceDesc->Buffer.Length < 256) ?
189                 SourceDesc->Buffer.Length : 256, DB_BYTE_DISPLAY, 0);
190         break;
191 
192     case ACPI_TYPE_STRING:
193 
194         AcpiOsPrintf ("[0x%.2X] \"%s\"\n",
195             SourceDesc->String.Length, SourceDesc->String.Pointer);
196         break;
197 
198     case ACPI_TYPE_PACKAGE:
199 
200         AcpiOsPrintf ("[Contains 0x%.2X Elements]\n",
201             SourceDesc->Package.Count);
202 
203         /* Output the entire contents of the package */
204 
205         for (i = 0; i < SourceDesc->Package.Count; i++)
206         {
207             AcpiExDoDebugObject (SourceDesc->Package.Elements[i],
208                 Level+4, i+1);
209         }
210         break;
211 
212     case ACPI_TYPE_LOCAL_REFERENCE:
213 
214         AcpiOsPrintf ("[%s] ", AcpiUtGetReferenceName (SourceDesc));
215 
216         /* Decode the reference */
217 
218         switch (SourceDesc->Reference.Class)
219         {
220         case ACPI_REFCLASS_INDEX:
221 
222             AcpiOsPrintf ("0x%X\n", SourceDesc->Reference.Value);
223             break;
224 
225         case ACPI_REFCLASS_TABLE:
226 
227             /* Case for DdbHandle */
228 
229             AcpiOsPrintf ("Table Index 0x%X\n", SourceDesc->Reference.Value);
230             return_VOID;
231 
232         default:
233 
234             break;
235         }
236 
237         AcpiOsPrintf ("  ");
238 
239         /* Check for valid node first, then valid object */
240 
241         if (SourceDesc->Reference.Node)
242         {
243             if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc->Reference.Node) !=
244                     ACPI_DESC_TYPE_NAMED)
245             {
246                 AcpiOsPrintf (" %p - Not a valid namespace node\n",
247                     SourceDesc->Reference.Node);
248             }
249             else
250             {
251                 AcpiOsPrintf ("Node %p [%4.4s] ", SourceDesc->Reference.Node,
252                     (SourceDesc->Reference.Node)->Name.Ascii);
253 
254                 switch ((SourceDesc->Reference.Node)->Type)
255                 {
256                 /* These types have no attached object */
257 
258                 case ACPI_TYPE_DEVICE:
259                     AcpiOsPrintf ("Device\n");
260                     break;
261 
262                 case ACPI_TYPE_THERMAL:
263                     AcpiOsPrintf ("Thermal Zone\n");
264                     break;
265 
266                 default:
267 
268                     AcpiExDoDebugObject ((SourceDesc->Reference.Node)->Object,
269                         Level+4, 0);
270                     break;
271                 }
272             }
273         }
274         else if (SourceDesc->Reference.Object)
275         {
276             if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc->Reference.Object) ==
277                     ACPI_DESC_TYPE_NAMED)
278             {
279                 AcpiExDoDebugObject (((ACPI_NAMESPACE_NODE *)
280                     SourceDesc->Reference.Object)->Object,
281                     Level+4, 0);
282             }
283             else
284             {
285                 ObjectDesc = SourceDesc->Reference.Object;
286                 Value = SourceDesc->Reference.Value;
287 
288                 switch (ObjectDesc->Common.Type)
289                 {
290                 case ACPI_TYPE_BUFFER:
291 
292                     AcpiOsPrintf ("Buffer[%u] = 0x%2.2X\n",
293                         Value, *SourceDesc->Reference.IndexPointer);
294                     break;
295 
296                 case ACPI_TYPE_STRING:
297 
298                     AcpiOsPrintf ("String[%u] = \"%c\" (0x%2.2X)\n",
299                         Value, *SourceDesc->Reference.IndexPointer,
300                         *SourceDesc->Reference.IndexPointer);
301                     break;
302 
303                 case ACPI_TYPE_PACKAGE:
304 
305                     AcpiOsPrintf ("Package[%u] = ", Value);
306                     AcpiExDoDebugObject (*SourceDesc->Reference.Where,
307                         Level+4, 0);
308                     break;
309 
310                 default:
311 
312                     AcpiOsPrintf ("Unknown Reference object type %X\n",
313                         ObjectDesc->Common.Type);
314                     break;
315                 }
316             }
317         }
318         break;
319 
320     default:
321 
322         AcpiOsPrintf ("%p\n", SourceDesc);
323         break;
324     }
325 
326     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "\n"));
327     return_VOID;
328 }
329 #endif
330 
331 
332 /*******************************************************************************
333  *
334  * FUNCTION:    AcpiExInterpreterTraceEnabled
335  *
336  * PARAMETERS:  Name                - Whether method name should be matched,
337  *                                    this should be checked before starting
338  *                                    the tracer
339  *
340  * RETURN:      TRUE if interpreter trace is enabled.
341  *
342  * DESCRIPTION: Check whether interpreter trace is enabled
343  *
344  ******************************************************************************/
345 
346 static BOOLEAN
347 AcpiExInterpreterTraceEnabled (
348     char                    *Name)
349 {
350 
351     /* Check if tracing is enabled */
352 
353     if (!(AcpiGbl_TraceFlags & ACPI_TRACE_ENABLED))
354     {
355         return (FALSE);
356     }
357 
358     /*
359      * Check if tracing is filtered:
360      *
361      * 1. If the tracer is started, AcpiGbl_TraceMethodObject should have
362      *    been filled by the trace starter
363      * 2. If the tracer is not started, AcpiGbl_TraceMethodName should be
364      *    matched if it is specified
365      * 3. If the tracer is oneshot style, AcpiGbl_TraceMethodName should
366      *    not be cleared by the trace stopper during the first match
367      */
368     if (AcpiGbl_TraceMethodObject)
369     {
370         return (TRUE);
371     }
372     if (Name &&
373         (AcpiGbl_TraceMethodName &&
374          strcmp (AcpiGbl_TraceMethodName, Name)))
375     {
376         return (FALSE);
377     }
378     if ((AcpiGbl_TraceFlags & ACPI_TRACE_ONESHOT) &&
379         !AcpiGbl_TraceMethodName)
380     {
381         return (FALSE);
382     }
383 
384     return (TRUE);
385 }
386 
387 
388 /*******************************************************************************
389  *
390  * FUNCTION:    AcpiExGetTraceEventName
391  *
392  * PARAMETERS:  Type            - Trace event type
393  *
394  * RETURN:      Trace event name.
395  *
396  * DESCRIPTION: Used to obtain the full trace event name.
397  *
398  ******************************************************************************/
399 
400 #ifdef ACPI_DEBUG_OUTPUT
401 
402 static const char *
403 AcpiExGetTraceEventName (
404     ACPI_TRACE_EVENT_TYPE   Type)
405 {
406     switch (Type)
407     {
408     case ACPI_TRACE_AML_METHOD:
409 
410         return "Method";
411 
412     case ACPI_TRACE_AML_OPCODE:
413 
414         return "Opcode";
415 
416     case ACPI_TRACE_AML_REGION:
417 
418         return "Region";
419 
420     default:
421 
422         return "";
423     }
424 }
425 
426 #endif
427 
428 
429 /*******************************************************************************
430  *
431  * FUNCTION:    AcpiExTracePoint
432  *
433  * PARAMETERS:  Type                - Trace event type
434  *              Begin               - TRUE if before execution
435  *              Aml                 - Executed AML address
436  *              Pathname            - Object path
437  *
438  * RETURN:      None
439  *
440  * DESCRIPTION: Internal interpreter execution trace.
441  *
442  ******************************************************************************/
443 
444 void
445 AcpiExTracePoint (
446     ACPI_TRACE_EVENT_TYPE   Type,
447     BOOLEAN                 Begin,
448     UINT8                   *Aml,
449     char                    *Pathname)
450 {
451 
452     ACPI_FUNCTION_NAME (ExTracePoint);
453 
454 
455     if (Pathname)
456     {
457         ACPI_DEBUG_PRINT ((ACPI_DB_TRACE_POINT,
458                 "%s %s [0x%p:%s] execution.\n",
459                 AcpiExGetTraceEventName (Type), Begin ? "Begin" : "End",
460                 Aml, Pathname));
461     }
462     else
463     {
464         ACPI_DEBUG_PRINT ((ACPI_DB_TRACE_POINT,
465                 "%s %s [0x%p] execution.\n",
466                 AcpiExGetTraceEventName (Type), Begin ? "Begin" : "End",
467                 Aml));
468     }
469 }
470 
471 
472 /*******************************************************************************
473  *
474  * FUNCTION:    AcpiExStartTraceMethod
475  *
476  * PARAMETERS:  MethodNode          - Node of the method
477  *              ObjDesc             - The method object
478  *              WalkState           - current state, NULL if not yet executing
479  *                                    a method.
480  *
481  * RETURN:      None
482  *
483  * DESCRIPTION: Start control method execution trace
484  *
485  ******************************************************************************/
486 
487 void
488 AcpiExStartTraceMethod (
489     ACPI_NAMESPACE_NODE     *MethodNode,
490     ACPI_OPERAND_OBJECT     *ObjDesc,
491     ACPI_WALK_STATE         *WalkState)
492 {
493     ACPI_STATUS             Status;
494     char                    *Pathname = NULL;
495     BOOLEAN                 Enabled = FALSE;
496 
497 
498     ACPI_FUNCTION_NAME (ExStartTraceMethod);
499 
500 
501     if (MethodNode)
502     {
503         Pathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE);
504     }
505 
506     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
507     if (ACPI_FAILURE (Status))
508     {
509         goto Exit;
510     }
511 
512     Enabled = AcpiExInterpreterTraceEnabled (Pathname);
513     if (Enabled && !AcpiGbl_TraceMethodObject)
514     {
515         AcpiGbl_TraceMethodObject = ObjDesc;
516         AcpiGbl_OriginalDbgLevel = AcpiDbgLevel;
517         AcpiGbl_OriginalDbgLayer = AcpiDbgLayer;
518         AcpiDbgLevel = ACPI_TRACE_LEVEL_ALL;
519         AcpiDbgLayer = ACPI_TRACE_LAYER_ALL;
520 
521         if (AcpiGbl_TraceDbgLevel)
522         {
523             AcpiDbgLevel = AcpiGbl_TraceDbgLevel;
524         }
525         if (AcpiGbl_TraceDbgLayer)
526         {
527             AcpiDbgLayer = AcpiGbl_TraceDbgLayer;
528         }
529     }
530     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
531 
532 Exit:
533     if (Enabled)
534     {
535         ACPI_TRACE_POINT (ACPI_TRACE_AML_METHOD, TRUE,
536                 ObjDesc ? ObjDesc->Method.AmlStart : NULL, Pathname);
537     }
538     if (Pathname)
539     {
540         ACPI_FREE (Pathname);
541     }
542 }
543 
544 
545 /*******************************************************************************
546  *
547  * FUNCTION:    AcpiExStopTraceMethod
548  *
549  * PARAMETERS:  MethodNode          - Node of the method
550  *              ObjDesc             - The method object
551  *              WalkState           - current state, NULL if not yet executing
552  *                                    a method.
553  *
554  * RETURN:      None
555  *
556  * DESCRIPTION: Stop control method execution trace
557  *
558  ******************************************************************************/
559 
560 void
561 AcpiExStopTraceMethod (
562     ACPI_NAMESPACE_NODE     *MethodNode,
563     ACPI_OPERAND_OBJECT     *ObjDesc,
564     ACPI_WALK_STATE         *WalkState)
565 {
566     ACPI_STATUS             Status;
567     char                    *Pathname = NULL;
568     BOOLEAN                 Enabled;
569 
570 
571     ACPI_FUNCTION_NAME (ExStopTraceMethod);
572 
573 
574     if (MethodNode)
575     {
576         Pathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE);
577     }
578 
579     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
580     if (ACPI_FAILURE (Status))
581     {
582         goto ExitPath;
583     }
584 
585     Enabled = AcpiExInterpreterTraceEnabled (NULL);
586 
587     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
588 
589     if (Enabled)
590     {
591         ACPI_TRACE_POINT (ACPI_TRACE_AML_METHOD, FALSE,
592                 ObjDesc ? ObjDesc->Method.AmlStart : NULL, Pathname);
593     }
594 
595     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
596     if (ACPI_FAILURE (Status))
597     {
598         goto ExitPath;
599     }
600 
601     /* Check whether the tracer should be stopped */
602 
603     if (AcpiGbl_TraceMethodObject == ObjDesc)
604     {
605         /* Disable further tracing if type is one-shot */
606 
607         if (AcpiGbl_TraceFlags & ACPI_TRACE_ONESHOT)
608         {
609             AcpiGbl_TraceMethodName = NULL;
610         }
611 
612         AcpiDbgLevel = AcpiGbl_OriginalDbgLevel;
613         AcpiDbgLayer = AcpiGbl_OriginalDbgLayer;
614         AcpiGbl_TraceMethodObject = NULL;
615     }
616 
617     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
618 
619 ExitPath:
620     if (Pathname)
621     {
622         ACPI_FREE (Pathname);
623     }
624 }
625 
626 
627 /*******************************************************************************
628  *
629  * FUNCTION:    AcpiExStartTraceOpcode
630  *
631  * PARAMETERS:  Op                  - The parser opcode object
632  *              WalkState           - current state, NULL if not yet executing
633  *                                    a method.
634  *
635  * RETURN:      None
636  *
637  * DESCRIPTION: Start opcode execution trace
638  *
639  ******************************************************************************/
640 
641 void
642 AcpiExStartTraceOpcode (
643     ACPI_PARSE_OBJECT       *Op,
644     ACPI_WALK_STATE         *WalkState)
645 {
646 
647     ACPI_FUNCTION_NAME (ExStartTraceOpcode);
648 
649 
650     if (AcpiExInterpreterTraceEnabled (NULL) &&
651         (AcpiGbl_TraceFlags & ACPI_TRACE_OPCODE))
652     {
653         ACPI_TRACE_POINT (ACPI_TRACE_AML_OPCODE, TRUE,
654                 Op->Common.Aml, Op->Common.AmlOpName);
655     }
656 }
657 
658 
659 /*******************************************************************************
660  *
661  * FUNCTION:    AcpiExStopTraceOpcode
662  *
663  * PARAMETERS:  Op                  - The parser opcode object
664  *              WalkState           - current state, NULL if not yet executing
665  *                                    a method.
666  *
667  * RETURN:      None
668  *
669  * DESCRIPTION: Stop opcode execution trace
670  *
671  ******************************************************************************/
672 
673 void
674 AcpiExStopTraceOpcode (
675     ACPI_PARSE_OBJECT       *Op,
676     ACPI_WALK_STATE         *WalkState)
677 {
678 
679     ACPI_FUNCTION_NAME (ExStopTraceOpcode);
680 
681 
682     if (AcpiExInterpreterTraceEnabled (NULL) &&
683         (AcpiGbl_TraceFlags & ACPI_TRACE_OPCODE))
684     {
685         ACPI_TRACE_POINT (ACPI_TRACE_AML_OPCODE, FALSE,
686                 Op->Common.Aml, Op->Common.AmlOpName);
687     }
688 }
689