exdebug.c revision 1.1.1.6 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 "acpi.h"
45 #include "accommon.h"
46 #include "acnamesp.h"
47 #include "acinterp.h"
48 #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