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