]>
Commit | Line | Data |
---|---|---|
95857638 | 1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
5df2e3ed BM |
2 | /****************************************************************************** |
3 | * | |
4 | * Module Name: extrace - Support for interpreter execution tracing | |
5 | * | |
da6f8320 | 6 | * Copyright (C) 2000 - 2018, Intel Corp. |
5df2e3ed | 7 | * |
95857638 | 8 | *****************************************************************************/ |
5df2e3ed BM |
9 | |
10 | #include <acpi/acpi.h> | |
11 | #include "accommon.h" | |
12 | #include "acnamesp.h" | |
13 | #include "acinterp.h" | |
14 | ||
15 | #define _COMPONENT ACPI_EXECUTER | |
16 | ACPI_MODULE_NAME("extrace") | |
17 | ||
18 | static union acpi_operand_object *acpi_gbl_trace_method_object = NULL; | |
19 | ||
20 | /* Local prototypes */ | |
21 | ||
22 | #ifdef ACPI_DEBUG_OUTPUT | |
23 | static const char *acpi_ex_get_trace_event_name(acpi_trace_event_type type); | |
24 | #endif | |
25 | ||
26 | /******************************************************************************* | |
27 | * | |
28 | * FUNCTION: acpi_ex_interpreter_trace_enabled | |
29 | * | |
30 | * PARAMETERS: name - Whether method name should be matched, | |
31 | * this should be checked before starting | |
32 | * the tracer | |
33 | * | |
34 | * RETURN: TRUE if interpreter trace is enabled. | |
35 | * | |
36 | * DESCRIPTION: Check whether interpreter trace is enabled | |
37 | * | |
38 | ******************************************************************************/ | |
39 | ||
40 | static u8 acpi_ex_interpreter_trace_enabled(char *name) | |
41 | { | |
42 | ||
43 | /* Check if tracing is enabled */ | |
44 | ||
45 | if (!(acpi_gbl_trace_flags & ACPI_TRACE_ENABLED)) { | |
46 | return (FALSE); | |
47 | } | |
48 | ||
49 | /* | |
50 | * Check if tracing is filtered: | |
51 | * | |
52 | * 1. If the tracer is started, acpi_gbl_trace_method_object should have | |
53 | * been filled by the trace starter | |
54 | * 2. If the tracer is not started, acpi_gbl_trace_method_name should be | |
55 | * matched if it is specified | |
56 | * 3. If the tracer is oneshot style, acpi_gbl_trace_method_name should | |
57 | * not be cleared by the trace stopper during the first match | |
58 | */ | |
59 | if (acpi_gbl_trace_method_object) { | |
60 | return (TRUE); | |
61 | } | |
62 | ||
63 | if (name && | |
64 | (acpi_gbl_trace_method_name && | |
65 | strcmp(acpi_gbl_trace_method_name, name))) { | |
66 | return (FALSE); | |
67 | } | |
68 | ||
69 | if ((acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) && | |
70 | !acpi_gbl_trace_method_name) { | |
71 | return (FALSE); | |
72 | } | |
73 | ||
74 | return (TRUE); | |
75 | } | |
76 | ||
77 | /******************************************************************************* | |
78 | * | |
79 | * FUNCTION: acpi_ex_get_trace_event_name | |
80 | * | |
81 | * PARAMETERS: type - Trace event type | |
82 | * | |
83 | * RETURN: Trace event name. | |
84 | * | |
85 | * DESCRIPTION: Used to obtain the full trace event name. | |
86 | * | |
87 | ******************************************************************************/ | |
88 | ||
89 | #ifdef ACPI_DEBUG_OUTPUT | |
90 | ||
91 | static const char *acpi_ex_get_trace_event_name(acpi_trace_event_type type) | |
92 | { | |
93 | ||
94 | switch (type) { | |
95 | case ACPI_TRACE_AML_METHOD: | |
96 | ||
97 | return "Method"; | |
98 | ||
99 | case ACPI_TRACE_AML_OPCODE: | |
100 | ||
101 | return "Opcode"; | |
102 | ||
103 | case ACPI_TRACE_AML_REGION: | |
104 | ||
105 | return "Region"; | |
106 | ||
107 | default: | |
108 | ||
109 | return ""; | |
110 | } | |
111 | } | |
112 | ||
113 | #endif | |
114 | ||
115 | /******************************************************************************* | |
116 | * | |
117 | * FUNCTION: acpi_ex_trace_point | |
118 | * | |
119 | * PARAMETERS: type - Trace event type | |
120 | * begin - TRUE if before execution | |
121 | * aml - Executed AML address | |
122 | * pathname - Object path | |
123 | * | |
124 | * RETURN: None | |
125 | * | |
126 | * DESCRIPTION: Internal interpreter execution trace. | |
127 | * | |
128 | ******************************************************************************/ | |
129 | ||
130 | void | |
131 | acpi_ex_trace_point(acpi_trace_event_type type, | |
132 | u8 begin, u8 *aml, char *pathname) | |
133 | { | |
134 | ||
135 | ACPI_FUNCTION_NAME(ex_trace_point); | |
136 | ||
137 | if (pathname) { | |
138 | ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT, | |
139 | "%s %s [0x%p:%s] execution.\n", | |
140 | acpi_ex_get_trace_event_name(type), | |
141 | begin ? "Begin" : "End", aml, pathname)); | |
142 | } else { | |
143 | ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT, | |
144 | "%s %s [0x%p] execution.\n", | |
145 | acpi_ex_get_trace_event_name(type), | |
146 | begin ? "Begin" : "End", aml)); | |
147 | } | |
148 | } | |
149 | ||
150 | /******************************************************************************* | |
151 | * | |
152 | * FUNCTION: acpi_ex_start_trace_method | |
153 | * | |
154 | * PARAMETERS: method_node - Node of the method | |
155 | * obj_desc - The method object | |
156 | * walk_state - current state, NULL if not yet executing | |
157 | * a method. | |
158 | * | |
159 | * RETURN: None | |
160 | * | |
161 | * DESCRIPTION: Start control method execution trace | |
162 | * | |
163 | ******************************************************************************/ | |
164 | ||
165 | void | |
166 | acpi_ex_start_trace_method(struct acpi_namespace_node *method_node, | |
167 | union acpi_operand_object *obj_desc, | |
168 | struct acpi_walk_state *walk_state) | |
169 | { | |
5df2e3ed BM |
170 | char *pathname = NULL; |
171 | u8 enabled = FALSE; | |
172 | ||
173 | ACPI_FUNCTION_NAME(ex_start_trace_method); | |
174 | ||
175 | if (method_node) { | |
176 | pathname = acpi_ns_get_normalized_pathname(method_node, TRUE); | |
177 | } | |
178 | ||
5df2e3ed BM |
179 | enabled = acpi_ex_interpreter_trace_enabled(pathname); |
180 | if (enabled && !acpi_gbl_trace_method_object) { | |
181 | acpi_gbl_trace_method_object = obj_desc; | |
182 | acpi_gbl_original_dbg_level = acpi_dbg_level; | |
183 | acpi_gbl_original_dbg_layer = acpi_dbg_layer; | |
184 | acpi_dbg_level = ACPI_TRACE_LEVEL_ALL; | |
185 | acpi_dbg_layer = ACPI_TRACE_LAYER_ALL; | |
186 | ||
187 | if (acpi_gbl_trace_dbg_level) { | |
188 | acpi_dbg_level = acpi_gbl_trace_dbg_level; | |
189 | } | |
190 | ||
191 | if (acpi_gbl_trace_dbg_layer) { | |
192 | acpi_dbg_layer = acpi_gbl_trace_dbg_layer; | |
193 | } | |
194 | } | |
195 | ||
5df2e3ed BM |
196 | if (enabled) { |
197 | ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, TRUE, | |
198 | obj_desc ? obj_desc->method.aml_start : NULL, | |
199 | pathname); | |
200 | } | |
201 | ||
202 | if (pathname) { | |
203 | ACPI_FREE(pathname); | |
204 | } | |
205 | } | |
206 | ||
207 | /******************************************************************************* | |
208 | * | |
209 | * FUNCTION: acpi_ex_stop_trace_method | |
210 | * | |
211 | * PARAMETERS: method_node - Node of the method | |
212 | * obj_desc - The method object | |
213 | * walk_state - current state, NULL if not yet executing | |
214 | * a method. | |
215 | * | |
216 | * RETURN: None | |
217 | * | |
218 | * DESCRIPTION: Stop control method execution trace | |
219 | * | |
220 | ******************************************************************************/ | |
221 | ||
222 | void | |
223 | acpi_ex_stop_trace_method(struct acpi_namespace_node *method_node, | |
224 | union acpi_operand_object *obj_desc, | |
225 | struct acpi_walk_state *walk_state) | |
226 | { | |
5df2e3ed BM |
227 | char *pathname = NULL; |
228 | u8 enabled; | |
229 | ||
230 | ACPI_FUNCTION_NAME(ex_stop_trace_method); | |
231 | ||
232 | if (method_node) { | |
233 | pathname = acpi_ns_get_normalized_pathname(method_node, TRUE); | |
234 | } | |
235 | ||
5df2e3ed BM |
236 | enabled = acpi_ex_interpreter_trace_enabled(NULL); |
237 | ||
5df2e3ed BM |
238 | if (enabled) { |
239 | ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, FALSE, | |
240 | obj_desc ? obj_desc->method.aml_start : NULL, | |
241 | pathname); | |
242 | } | |
243 | ||
5df2e3ed BM |
244 | /* Check whether the tracer should be stopped */ |
245 | ||
246 | if (acpi_gbl_trace_method_object == obj_desc) { | |
247 | ||
248 | /* Disable further tracing if type is one-shot */ | |
249 | ||
250 | if (acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) { | |
251 | acpi_gbl_trace_method_name = NULL; | |
252 | } | |
253 | ||
254 | acpi_dbg_level = acpi_gbl_original_dbg_level; | |
255 | acpi_dbg_layer = acpi_gbl_original_dbg_layer; | |
256 | acpi_gbl_trace_method_object = NULL; | |
257 | } | |
258 | ||
5df2e3ed BM |
259 | if (pathname) { |
260 | ACPI_FREE(pathname); | |
261 | } | |
262 | } | |
263 | ||
264 | /******************************************************************************* | |
265 | * | |
266 | * FUNCTION: acpi_ex_start_trace_opcode | |
267 | * | |
268 | * PARAMETERS: op - The parser opcode object | |
269 | * walk_state - current state, NULL if not yet executing | |
270 | * a method. | |
271 | * | |
272 | * RETURN: None | |
273 | * | |
274 | * DESCRIPTION: Start opcode execution trace | |
275 | * | |
276 | ******************************************************************************/ | |
277 | ||
278 | void | |
279 | acpi_ex_start_trace_opcode(union acpi_parse_object *op, | |
280 | struct acpi_walk_state *walk_state) | |
281 | { | |
282 | ||
283 | ACPI_FUNCTION_NAME(ex_start_trace_opcode); | |
284 | ||
285 | if (acpi_ex_interpreter_trace_enabled(NULL) && | |
286 | (acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) { | |
287 | ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, TRUE, | |
288 | op->common.aml, op->common.aml_op_name); | |
289 | } | |
290 | } | |
291 | ||
292 | /******************************************************************************* | |
293 | * | |
294 | * FUNCTION: acpi_ex_stop_trace_opcode | |
295 | * | |
296 | * PARAMETERS: op - The parser opcode object | |
297 | * walk_state - current state, NULL if not yet executing | |
298 | * a method. | |
299 | * | |
300 | * RETURN: None | |
301 | * | |
302 | * DESCRIPTION: Stop opcode execution trace | |
303 | * | |
304 | ******************************************************************************/ | |
305 | ||
306 | void | |
307 | acpi_ex_stop_trace_opcode(union acpi_parse_object *op, | |
308 | struct acpi_walk_state *walk_state) | |
309 | { | |
310 | ||
311 | ACPI_FUNCTION_NAME(ex_stop_trace_opcode); | |
312 | ||
313 | if (acpi_ex_interpreter_trace_enabled(NULL) && | |
314 | (acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) { | |
315 | ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, FALSE, | |
316 | op->common.aml, op->common.aml_op_name); | |
317 | } | |
318 | } |