xref: /linux/kernel/trace/trace_boot.c (revision 6439079365dcb33c6701f5f0e480ac2c17312b6b)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * trace_boot.c
4  * Tracing kernel boot-time
5  */
6 
7 #define pr_fmt(fmt)	"trace_boot: " fmt
8 
9 #include <linux/bootconfig.h>
10 #include <linux/cpumask.h>
11 #include <linux/ftrace.h>
12 #include <linux/init.h>
13 #include <linux/kernel.h>
14 #include <linux/mutex.h>
15 #include <linux/string.h>
16 #include <linux/slab.h>
17 #include <linux/trace.h>
18 #include <linux/trace_events.h>
19 
20 #include "trace.h"
21 #include "trace_dynevent.h"
22 
23 #define MAX_BUF_LEN 256
24 
25 static void __init
trace_boot_set_instance_options(struct trace_array * tr,struct xbc_node * node)26 trace_boot_set_instance_options(struct trace_array *tr, struct xbc_node *node)
27 {
28 	struct xbc_node *anode;
29 	const char *p;
30 	char buf[MAX_BUF_LEN];
31 	unsigned long v = 0;
32 
33 	/* Common ftrace options */
34 	xbc_node_for_each_array_value(node, "options", anode, p) {
35 		if (strscpy(buf, p, ARRAY_SIZE(buf)) < 0) {
36 			pr_err("String is too long: %s\n", p);
37 			continue;
38 		}
39 
40 		if (trace_set_options(tr, buf) < 0)
41 			pr_err("Failed to set option: %s\n", buf);
42 	}
43 
44 	p = xbc_node_find_value(node, "tracing_on", NULL);
45 	if (p && *p != '\0') {
46 		if (kstrtoul(p, 10, &v))
47 			pr_err("Failed to set tracing on: %s\n", p);
48 		if (v)
49 			tracer_tracing_on(tr);
50 		else
51 			tracer_tracing_off(tr);
52 	}
53 
54 	p = xbc_node_find_value(node, "trace_clock", NULL);
55 	if (p && *p != '\0') {
56 		if (tracing_set_clock(tr, p) < 0)
57 			pr_err("Failed to set trace clock: %s\n", p);
58 	}
59 
60 	p = xbc_node_find_value(node, "buffer_size", NULL);
61 	if (p && *p != '\0') {
62 		v = memparse(p, NULL);
63 		if (v < PAGE_SIZE)
64 			pr_err("Buffer size is too small: %s\n", p);
65 		if (trace_array_is_readonly(tr) ||
66 		    tracing_resize_ring_buffer(tr, v, RING_BUFFER_ALL_CPUS) < 0)
67 			pr_err("Failed to resize trace buffer to %s\n", p);
68 	}
69 
70 	p = xbc_node_find_value(node, "cpumask", NULL);
71 	if (p && *p != '\0') {
72 		cpumask_var_t new_mask;
73 
74 		if (alloc_cpumask_var(&new_mask, GFP_KERNEL)) {
75 			if (cpumask_parse(p, new_mask) < 0 ||
76 			    tracing_set_cpumask(tr, new_mask) < 0)
77 				pr_err("Failed to set new CPU mask %s\n", p);
78 			free_cpumask_var(new_mask);
79 		}
80 	}
81 }
82 
83 #ifdef CONFIG_EVENT_TRACING
84 static void __init
trace_boot_enable_events(struct trace_array * tr,struct xbc_node * node)85 trace_boot_enable_events(struct trace_array *tr, struct xbc_node *node)
86 {
87 	struct xbc_node *anode;
88 	char buf[MAX_BUF_LEN];
89 	const char *p;
90 
91 	xbc_node_for_each_array_value(node, "events", anode, p) {
92 		if (strscpy(buf, p, ARRAY_SIZE(buf)) < 0) {
93 			pr_err("String is too long: %s\n", p);
94 			continue;
95 		}
96 
97 		if (ftrace_set_clr_event(tr, buf, 1) < 0)
98 			pr_err("Failed to enable event: %s\n", p);
99 	}
100 }
101 
102 #ifdef CONFIG_KPROBE_EVENTS
103 static int __init
trace_boot_add_kprobe_event(struct xbc_node * node,const char * event)104 trace_boot_add_kprobe_event(struct xbc_node *node, const char *event)
105 {
106 	struct dynevent_cmd cmd;
107 	struct xbc_node *anode;
108 	char buf[MAX_BUF_LEN];
109 	const char *val;
110 	int ret = 0;
111 
112 	xbc_node_for_each_array_value(node, "probes", anode, val) {
113 		kprobe_event_cmd_init(&cmd, buf, MAX_BUF_LEN);
114 
115 		ret = kprobe_event_gen_cmd_start(&cmd, event, val);
116 		if (ret) {
117 			pr_err("Failed to generate probe: %s\n", buf);
118 			break;
119 		}
120 
121 		ret = kprobe_event_gen_cmd_end(&cmd);
122 		if (ret) {
123 			pr_err("Failed to add probe: %s\n", buf);
124 			break;
125 		}
126 	}
127 
128 	return ret;
129 }
130 #else
131 static inline int __init
trace_boot_add_kprobe_event(struct xbc_node * node,const char * event)132 trace_boot_add_kprobe_event(struct xbc_node *node, const char *event)
133 {
134 	pr_err("Kprobe event is not supported.\n");
135 	return -ENOTSUPP;
136 }
137 #endif
138 
139 #ifdef CONFIG_SYNTH_EVENTS
140 static int __init
trace_boot_add_synth_event(struct xbc_node * node,const char * event)141 trace_boot_add_synth_event(struct xbc_node *node, const char *event)
142 {
143 	struct dynevent_cmd cmd;
144 	struct xbc_node *anode;
145 	char buf[MAX_BUF_LEN];
146 	const char *p;
147 	int ret;
148 
149 	synth_event_cmd_init(&cmd, buf, MAX_BUF_LEN);
150 
151 	ret = synth_event_gen_cmd_start(&cmd, event, NULL);
152 	if (ret)
153 		return ret;
154 
155 	xbc_node_for_each_array_value(node, "fields", anode, p) {
156 		ret = synth_event_add_field_str(&cmd, p);
157 		if (ret)
158 			return ret;
159 	}
160 
161 	ret = synth_event_gen_cmd_end(&cmd);
162 	if (ret < 0)
163 		pr_err("Failed to add synthetic event: %s\n", buf);
164 
165 	return ret;
166 }
167 #else
168 static inline int __init
trace_boot_add_synth_event(struct xbc_node * node,const char * event)169 trace_boot_add_synth_event(struct xbc_node *node, const char *event)
170 {
171 	pr_err("Synthetic event is not supported.\n");
172 	return -ENOTSUPP;
173 }
174 #endif
175 
176 #if defined(CONFIG_EPROBE_EVENTS) || defined(CONFIG_FPROBE_EVENTS)
177 static int __init
trace_boot_add_probe_event(struct xbc_node * node,const char * group,const char * event,char type,const char * type_name)178 trace_boot_add_probe_event(struct xbc_node *node, const char *group,
179 			    const char *event, char type, const char *type_name)
180 {
181 	struct xbc_node *anode;
182 	char buf[MAX_BUF_LEN];
183 	const char *val;
184 	int ret = 0;
185 
186 	xbc_node_for_each_array_value(node, "probes", anode, val) {
187 		if (val[0] == type && (val[1] == ':' || isspace(val[1]))) {
188 			ret = strscpy(buf, val, MAX_BUF_LEN);
189 			if (ret < 0) {
190 				pr_err("%s command is too long: %s\n", type_name, val);
191 				break;
192 			}
193 		} else {
194 			ret = snprintf(buf, MAX_BUF_LEN, "%c:%s/%s %s", type, group, event, val);
195 			if (ret >= MAX_BUF_LEN || ret < 0) {
196 				pr_err("%s command is too long: %c:%s/%s %s\n",
197 				       type_name, type, group, event, val);
198 				ret = -E2BIG;
199 				break;
200 			}
201 		}
202 
203 		ret = dyn_event_create(buf, NULL);
204 		if (ret) {
205 			pr_err("Failed to add %s: %s\n", type_name, buf);
206 			break;
207 		}
208 	}
209 
210 	return ret;
211 }
212 #endif
213 
214 #ifdef CONFIG_EPROBE_EVENTS
215 static inline int __init
trace_boot_add_eprobe_event(struct xbc_node * node,const char * group,const char * event)216 trace_boot_add_eprobe_event(struct xbc_node *node, const char *group,
217 			    const char *event)
218 {
219 	return trace_boot_add_probe_event(node, group, event, 'e', "eprobe");
220 }
221 #else
222 static inline int __init
trace_boot_add_eprobe_event(struct xbc_node * node,const char * group,const char * event)223 trace_boot_add_eprobe_event(struct xbc_node *node, const char *group,
224 			    const char *event)
225 {
226 	pr_err("Event probe is not supported.\n");
227 	return -EOPNOTSUPP;
228 }
229 #endif
230 
231 #ifdef CONFIG_FPROBE_EVENTS
232 static inline int __init
trace_boot_add_fprobe_event(struct xbc_node * node,const char * group,const char * event)233 trace_boot_add_fprobe_event(struct xbc_node *node, const char *group,
234 			    const char *event)
235 {
236 	return trace_boot_add_probe_event(node, group, event, 'f', "fprobe");
237 }
238 
239 static inline int __init
trace_boot_add_tprobe_event(struct xbc_node * node,const char * group,const char * event)240 trace_boot_add_tprobe_event(struct xbc_node *node, const char *group,
241 			    const char *event)
242 {
243 	return trace_boot_add_probe_event(node, group, event, 't', "tprobe");
244 }
245 #else
246 static inline int __init
trace_boot_add_fprobe_event(struct xbc_node * node,const char * group,const char * event)247 trace_boot_add_fprobe_event(struct xbc_node *node, const char *group,
248 			    const char *event)
249 {
250 	pr_err("Fprobe event is not supported.\n");
251 	return -EOPNOTSUPP;
252 }
253 
254 static inline int __init
trace_boot_add_tprobe_event(struct xbc_node * node,const char * group,const char * event)255 trace_boot_add_tprobe_event(struct xbc_node *node, const char *group,
256 			    const char *event)
257 {
258 	pr_err("Tracepoint probe is not supported.\n");
259 	return -EOPNOTSUPP;
260 }
261 #endif
262 
263 #ifdef CONFIG_HIST_TRIGGERS
264 static int __init __printf(3, 4)
append_printf(char ** bufp,char * end,const char * fmt,...)265 append_printf(char **bufp, char *end, const char *fmt, ...)
266 {
267 	va_list args;
268 	int ret;
269 
270 	if (*bufp == end)
271 		return -ENOSPC;
272 
273 	va_start(args, fmt);
274 	ret = vsnprintf(*bufp, end - *bufp, fmt, args);
275 	if (ret < end - *bufp) {
276 		*bufp += ret;
277 	} else {
278 		*bufp = end;
279 		ret = -ERANGE;
280 	}
281 	va_end(args);
282 
283 	return ret;
284 }
285 
286 static int __init
append_str_nospace(char ** bufp,char * end,const char * str)287 append_str_nospace(char **bufp, char *end, const char *str)
288 {
289 	char *p = *bufp;
290 	int len;
291 
292 	while (p < end - 1 && *str != '\0') {
293 		if (!isspace(*str))
294 			*(p++) = *str;
295 		str++;
296 	}
297 	*p = '\0';
298 	if (p == end - 1) {
299 		*bufp = end;
300 		return -ENOSPC;
301 	}
302 	len = p - *bufp;
303 	*bufp = p;
304 	return (int)len;
305 }
306 
307 static int __init
trace_boot_hist_add_array(struct xbc_node * hnode,char ** bufp,char * end,const char * key)308 trace_boot_hist_add_array(struct xbc_node *hnode, char **bufp,
309 			  char *end, const char *key)
310 {
311 	struct xbc_node *anode;
312 	const char *p;
313 	char sep;
314 
315 	p = xbc_node_find_value(hnode, key, &anode);
316 	if (p) {
317 		if (!anode) {
318 			pr_err("hist.%s requires value(s).\n", key);
319 			return -EINVAL;
320 		}
321 
322 		append_printf(bufp, end, ":%s", key);
323 		sep = '=';
324 		xbc_array_for_each_value(anode, p) {
325 			append_printf(bufp, end, "%c%s", sep, p);
326 			if (sep == '=')
327 				sep = ',';
328 		}
329 	} else
330 		return -ENOENT;
331 
332 	return 0;
333 }
334 
335 static int __init
trace_boot_hist_add_one_handler(struct xbc_node * hnode,char ** bufp,char * end,const char * handler,const char * param)336 trace_boot_hist_add_one_handler(struct xbc_node *hnode, char **bufp,
337 				char *end, const char *handler,
338 				const char *param)
339 {
340 	struct xbc_node *knode, *anode;
341 	const char *p;
342 	char sep;
343 
344 	/* Compose 'handler' parameter */
345 	p = xbc_node_find_value(hnode, param, NULL);
346 	if (!p) {
347 		pr_err("hist.%s requires '%s' option.\n",
348 		       xbc_node_get_data(hnode), param);
349 		return -EINVAL;
350 	}
351 	append_printf(bufp, end, ":%s(%s)", handler, p);
352 
353 	/* Compose 'action' parameter */
354 	knode = xbc_node_find_subkey(hnode, "trace");
355 	if (!knode)
356 		knode = xbc_node_find_subkey(hnode, "save");
357 
358 	if (knode) {
359 		anode = xbc_node_get_child(knode);
360 		if (!anode || !xbc_node_is_value(anode)) {
361 			pr_err("hist.%s.%s requires value(s).\n",
362 			       xbc_node_get_data(hnode),
363 			       xbc_node_get_data(knode));
364 			return -EINVAL;
365 		}
366 
367 		append_printf(bufp, end, ".%s", xbc_node_get_data(knode));
368 		sep = '(';
369 		xbc_array_for_each_value(anode, p) {
370 			append_printf(bufp, end, "%c%s", sep, p);
371 			if (sep == '(')
372 				sep = ',';
373 		}
374 		append_printf(bufp, end, ")");
375 	} else if (xbc_node_find_subkey(hnode, "snapshot")) {
376 		append_printf(bufp, end, ".snapshot()");
377 	} else {
378 		pr_err("hist.%s requires an action.\n",
379 		       xbc_node_get_data(hnode));
380 		return -EINVAL;
381 	}
382 
383 	return 0;
384 }
385 
386 static int __init
trace_boot_hist_add_handlers(struct xbc_node * hnode,char ** bufp,char * end,const char * param)387 trace_boot_hist_add_handlers(struct xbc_node *hnode, char **bufp,
388 			     char *end, const char *param)
389 {
390 	struct xbc_node *node;
391 	const char *p, *handler;
392 	int ret = 0;
393 
394 	handler = xbc_node_get_data(hnode);
395 
396 	xbc_node_for_each_subkey(hnode, node) {
397 		p = xbc_node_get_data(node);
398 		if (!isdigit(p[0]))
399 			continue;
400 		/* All digit started node should be instances. */
401 		ret = trace_boot_hist_add_one_handler(node, bufp, end, handler, param);
402 		if (ret < 0)
403 			break;
404 	}
405 
406 	if (xbc_node_find_subkey(hnode, param))
407 		ret = trace_boot_hist_add_one_handler(hnode, bufp, end, handler, param);
408 
409 	return ret;
410 }
411 
412 /*
413  * Histogram boottime tracing syntax.
414  *
415  * ftrace.[instance.INSTANCE.]event.GROUP.EVENT.hist[.N] {
416  *	keys = <KEY>[,...]
417  *	values = <VAL>[,...]
418  *	sort = <SORT-KEY>[,...]
419  *	size = <ENTRIES>
420  *	name = <HISTNAME>
421  *	var { <VAR> = <EXPR> ... }
422  *	pause|continue|clear
423  *	onmax|onchange[.N] { var = <VAR>; <ACTION> [= <PARAM>] }
424  *	onmatch[.N] { event = <EVENT>; <ACTION> [= <PARAM>] }
425  *	filter = <FILTER>
426  * }
427  *
428  * Where <ACTION> are;
429  *
430  *	trace = <EVENT>, <ARG1>[, ...]
431  *	save = <ARG1>[, ...]
432  *	snapshot
433  */
434 static int __init
trace_boot_compose_hist_cmd(struct xbc_node * hnode,char * buf,size_t size)435 trace_boot_compose_hist_cmd(struct xbc_node *hnode, char *buf, size_t size)
436 {
437 	struct xbc_node *node, *knode;
438 	char *end = buf + size;
439 	const char *p;
440 	int ret = 0;
441 
442 	append_printf(&buf, end, "hist");
443 
444 	ret = trace_boot_hist_add_array(hnode, &buf, end, "keys");
445 	if (ret < 0) {
446 		if (ret == -ENOENT)
447 			pr_err("hist requires keys.\n");
448 		return -EINVAL;
449 	}
450 
451 	ret = trace_boot_hist_add_array(hnode, &buf, end, "values");
452 	if (ret == -EINVAL)
453 		return ret;
454 	ret = trace_boot_hist_add_array(hnode, &buf, end, "sort");
455 	if (ret == -EINVAL)
456 		return ret;
457 
458 	p = xbc_node_find_value(hnode, "size", NULL);
459 	if (p)
460 		append_printf(&buf, end, ":size=%s", p);
461 
462 	p = xbc_node_find_value(hnode, "name", NULL);
463 	if (p)
464 		append_printf(&buf, end, ":name=%s", p);
465 
466 	node = xbc_node_find_subkey(hnode, "var");
467 	if (node) {
468 		xbc_node_for_each_key_value(node, knode, p) {
469 			/* Expression must not include spaces. */
470 			append_printf(&buf, end, ":%s=",
471 				      xbc_node_get_data(knode));
472 			append_str_nospace(&buf, end, p);
473 		}
474 	}
475 
476 	/* Histogram control attributes (mutual exclusive) */
477 	if (xbc_node_find_value(hnode, "pause", NULL))
478 		append_printf(&buf, end, ":pause");
479 	else if (xbc_node_find_value(hnode, "continue", NULL))
480 		append_printf(&buf, end, ":continue");
481 	else if (xbc_node_find_value(hnode, "clear", NULL))
482 		append_printf(&buf, end, ":clear");
483 
484 	/* Histogram handler and actions */
485 	node = xbc_node_find_subkey(hnode, "onmax");
486 	if (node && trace_boot_hist_add_handlers(node, &buf, end, "var") < 0)
487 		return -EINVAL;
488 	node = xbc_node_find_subkey(hnode, "onchange");
489 	if (node && trace_boot_hist_add_handlers(node, &buf, end, "var") < 0)
490 		return -EINVAL;
491 	node = xbc_node_find_subkey(hnode, "onmatch");
492 	if (node && trace_boot_hist_add_handlers(node, &buf, end, "event") < 0)
493 		return -EINVAL;
494 
495 	p = xbc_node_find_value(hnode, "filter", NULL);
496 	if (p)
497 		append_printf(&buf, end, " if %s", p);
498 
499 	if (buf == end) {
500 		pr_err("hist exceeds the max command length.\n");
501 		return -E2BIG;
502 	}
503 
504 	return 0;
505 }
506 
507 static void __init
trace_boot_init_histograms(struct trace_event_file * file,struct xbc_node * hnode,char * buf,size_t size)508 trace_boot_init_histograms(struct trace_event_file *file,
509 			   struct xbc_node *hnode, char *buf, size_t size)
510 {
511 	struct xbc_node *node;
512 	const char *p;
513 	char *tmp;
514 
515 	xbc_node_for_each_subkey(hnode, node) {
516 		p = xbc_node_get_data(node);
517 		if (!isdigit(p[0]))
518 			continue;
519 		/* All digit started node should be instances. */
520 		if (trace_boot_compose_hist_cmd(node, buf, size) == 0) {
521 			tmp = kstrdup(buf, GFP_KERNEL);
522 			if (!tmp)
523 				return;
524 			if (trigger_process_regex(file, buf) < 0)
525 				pr_err("Failed to apply hist trigger: %s\n", tmp);
526 			kfree(tmp);
527 		}
528 	}
529 
530 	if (xbc_node_find_subkey(hnode, "keys")) {
531 		if (trace_boot_compose_hist_cmd(hnode, buf, size) == 0) {
532 			tmp = kstrdup(buf, GFP_KERNEL);
533 			if (!tmp)
534 				return;
535 			if (trigger_process_regex(file, buf) < 0)
536 				pr_err("Failed to apply hist trigger: %s\n", tmp);
537 			kfree(tmp);
538 		}
539 	}
540 }
541 #else
542 static void __init
trace_boot_init_histograms(struct trace_event_file * file,struct xbc_node * hnode,char * buf,size_t size)543 trace_boot_init_histograms(struct trace_event_file *file,
544 			   struct xbc_node *hnode, char *buf, size_t size)
545 {
546 	/* do nothing */
547 }
548 #endif
549 
550 static void __init
trace_boot_init_one_event(struct trace_array * tr,struct xbc_node * gnode,struct xbc_node * enode)551 trace_boot_init_one_event(struct trace_array *tr, struct xbc_node *gnode,
552 			  struct xbc_node *enode)
553 {
554 	struct trace_event_file *file;
555 	struct xbc_node *anode;
556 	char buf[MAX_BUF_LEN];
557 	const char *p, *group, *event;
558 
559 	group = xbc_node_get_data(gnode);
560 	event = xbc_node_get_data(enode);
561 
562 	if (!strcmp(group, "kprobes"))
563 		if (trace_boot_add_kprobe_event(enode, event) < 0)
564 			return;
565 	if (!strcmp(group, "synthetic"))
566 		if (trace_boot_add_synth_event(enode, event) < 0)
567 			return;
568 	if (!strcmp(group, "eprobes"))
569 		if (trace_boot_add_eprobe_event(enode, group, event) < 0)
570 			return;
571 	if (!strcmp(group, "fprobes"))
572 		if (trace_boot_add_fprobe_event(enode, group, event) < 0)
573 			return;
574 	if (!strcmp(group, "tracepoints") || !strcmp(group, "tprobes"))
575 		if (trace_boot_add_tprobe_event(enode, group, event) < 0)
576 			return;
577 
578 	mutex_lock(&event_mutex);
579 	file = find_event_file(tr, group, event);
580 	if (!file) {
581 		pr_err("Failed to find event: %s:%s\n", group, event);
582 		goto out;
583 	}
584 
585 	p = xbc_node_find_value(enode, "filter", NULL);
586 	if (p && *p != '\0') {
587 		if (strscpy(buf, p, ARRAY_SIZE(buf)) < 0)
588 			pr_err("filter string is too long: %s\n", p);
589 		else if (apply_event_filter(file, buf) < 0)
590 			pr_err("Failed to apply filter: %s\n", buf);
591 	}
592 
593 	if (IS_ENABLED(CONFIG_HIST_TRIGGERS)) {
594 		xbc_node_for_each_array_value(enode, "actions", anode, p) {
595 			if (strscpy(buf, p, ARRAY_SIZE(buf)) < 0)
596 				pr_err("action string is too long: %s\n", p);
597 			else if (trigger_process_regex(file, buf) < 0)
598 				pr_err("Failed to apply an action: %s\n", p);
599 		}
600 		anode = xbc_node_find_subkey(enode, "hist");
601 		if (anode)
602 			trace_boot_init_histograms(file, anode, buf, ARRAY_SIZE(buf));
603 	} else if (xbc_node_find_value(enode, "actions", NULL))
604 		pr_err("Failed to apply event actions because CONFIG_HIST_TRIGGERS is not set.\n");
605 
606 	if (xbc_node_find_value(enode, "enable", NULL)) {
607 		if (trace_event_enable_disable(file, 1, 0) < 0)
608 			pr_err("Failed to enable event node: %s:%s\n",
609 				group, event);
610 	}
611 out:
612 	mutex_unlock(&event_mutex);
613 }
614 
615 static void __init
trace_boot_init_events(struct trace_array * tr,struct xbc_node * node)616 trace_boot_init_events(struct trace_array *tr, struct xbc_node *node)
617 {
618 	struct xbc_node *gnode, *enode;
619 	bool enable, enable_all = false;
620 	const char *data;
621 
622 	node = xbc_node_find_subkey(node, "event");
623 	if (!node)
624 		return;
625 	/* per-event key starts with "event.GROUP.EVENT" */
626 	xbc_node_for_each_subkey(node, gnode) {
627 		data = xbc_node_get_data(gnode);
628 		if (!strcmp(data, "enable")) {
629 			enable_all = true;
630 			continue;
631 		}
632 		enable = false;
633 		xbc_node_for_each_subkey(gnode, enode) {
634 			data = xbc_node_get_data(enode);
635 			if (!strcmp(data, "enable")) {
636 				enable = true;
637 				continue;
638 			}
639 			trace_boot_init_one_event(tr, gnode, enode);
640 		}
641 		/* Event enablement must be done after event settings */
642 		if (enable) {
643 			data = xbc_node_get_data(gnode);
644 			trace_array_set_clr_event(tr, data, NULL, true);
645 		}
646 	}
647 	/* Ditto */
648 	if (enable_all)
649 		trace_array_set_clr_event(tr, NULL, NULL, true);
650 }
651 #else
652 #define trace_boot_enable_events(tr, node) do {} while (0)
653 #define trace_boot_init_events(tr, node) do {} while (0)
654 #endif
655 
656 #ifdef CONFIG_DYNAMIC_FTRACE
657 static void __init
trace_boot_set_ftrace_filter(struct trace_array * tr,struct xbc_node * node)658 trace_boot_set_ftrace_filter(struct trace_array *tr, struct xbc_node *node)
659 {
660 	struct xbc_node *anode;
661 	const char *p;
662 	char *q;
663 
664 	xbc_node_for_each_array_value(node, "ftrace.filters", anode, p) {
665 		q = kstrdup(p, GFP_KERNEL);
666 		if (!q)
667 			return;
668 		if (ftrace_set_filter(tr->ops, q, strlen(q), 0) < 0)
669 			pr_err("Failed to add %s to ftrace filter\n", p);
670 		else
671 			ftrace_filter_param = true;
672 		kfree(q);
673 	}
674 	xbc_node_for_each_array_value(node, "ftrace.notraces", anode, p) {
675 		q = kstrdup(p, GFP_KERNEL);
676 		if (!q)
677 			return;
678 		if (ftrace_set_notrace(tr->ops, q, strlen(q), 0) < 0)
679 			pr_err("Failed to add %s to ftrace filter\n", p);
680 		else
681 			ftrace_filter_param = true;
682 		kfree(q);
683 	}
684 }
685 #else
686 #define trace_boot_set_ftrace_filter(tr, node) do {} while (0)
687 #endif
688 
689 static void __init
trace_boot_enable_tracer(struct trace_array * tr,struct xbc_node * node)690 trace_boot_enable_tracer(struct trace_array *tr, struct xbc_node *node)
691 {
692 	const char *p;
693 
694 	trace_boot_set_ftrace_filter(tr, node);
695 
696 	p = xbc_node_find_value(node, "tracer", NULL);
697 	if (p && *p != '\0') {
698 		if (trace_array_is_readonly(tr) || tracing_set_tracer(tr, p) < 0)
699 			pr_err("Failed to set given tracer: %s\n", p);
700 	}
701 
702 	/* Since tracer can free snapshot buffer, allocate snapshot here.*/
703 	if (xbc_node_find_value(node, "alloc_snapshot", NULL)) {
704 		if (tracing_alloc_snapshot_instance(tr) < 0)
705 			pr_err("Failed to allocate snapshot buffer\n");
706 	}
707 }
708 
709 static void __init
trace_boot_init_one_instance(struct trace_array * tr,struct xbc_node * node)710 trace_boot_init_one_instance(struct trace_array *tr, struct xbc_node *node)
711 {
712 	trace_boot_set_instance_options(tr, node);
713 	trace_boot_init_events(tr, node);
714 	trace_boot_enable_events(tr, node);
715 	trace_boot_enable_tracer(tr, node);
716 }
717 
718 static void __init
trace_boot_init_instances(struct xbc_node * node)719 trace_boot_init_instances(struct xbc_node *node)
720 {
721 	struct xbc_node *inode;
722 	struct trace_array *tr;
723 	const char *p;
724 
725 	node = xbc_node_find_subkey(node, "instance");
726 	if (!node)
727 		return;
728 
729 	xbc_node_for_each_subkey(node, inode) {
730 		p = xbc_node_get_data(inode);
731 		if (!p || *p == '\0')
732 			continue;
733 
734 		tr = trace_array_get_by_name(p, NULL);
735 		if (!tr) {
736 			pr_err("Failed to get trace instance %s\n", p);
737 			continue;
738 		}
739 		trace_boot_init_one_instance(tr, inode);
740 		trace_array_put(tr);
741 	}
742 }
743 
trace_boot_init(void)744 static int __init trace_boot_init(void)
745 {
746 	struct xbc_node *trace_node;
747 	struct trace_array *tr;
748 
749 	trace_node = xbc_find_node("ftrace");
750 	if (!trace_node)
751 		return 0;
752 
753 	tr = top_trace_array();
754 	if (!tr)
755 		return 0;
756 
757 	/* Global trace array is also one instance */
758 	trace_boot_init_one_instance(tr, trace_node);
759 	trace_boot_init_instances(trace_node);
760 
761 	disable_tracing_selftest("running boot-time tracing");
762 
763 	return 0;
764 }
765 /*
766  * Start tracing at the end of core-initcall, so that it starts tracing
767  * from the beginning of postcore_initcall.
768  */
769 core_initcall_sync(trace_boot_init);
770