xref: /openbmc/linux/kernel/trace/trace_boot.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
19c5b9d3dSMasami Hiramatsu // SPDX-License-Identifier: GPL-2.0
29c5b9d3dSMasami Hiramatsu /*
39c5b9d3dSMasami Hiramatsu  * trace_boot.c
49c5b9d3dSMasami Hiramatsu  * Tracing kernel boot-time
59c5b9d3dSMasami Hiramatsu  */
69c5b9d3dSMasami Hiramatsu 
79c5b9d3dSMasami Hiramatsu #define pr_fmt(fmt)	"trace_boot: " fmt
89c5b9d3dSMasami Hiramatsu 
976a598ecSMasami Hiramatsu #include <linux/bootconfig.h>
1076a598ecSMasami Hiramatsu #include <linux/cpumask.h>
119c5b9d3dSMasami Hiramatsu #include <linux/ftrace.h>
129c5b9d3dSMasami Hiramatsu #include <linux/init.h>
1376a598ecSMasami Hiramatsu #include <linux/kernel.h>
1476a598ecSMasami Hiramatsu #include <linux/mutex.h>
1576a598ecSMasami Hiramatsu #include <linux/string.h>
1676a598ecSMasami Hiramatsu #include <linux/slab.h>
1776a598ecSMasami Hiramatsu #include <linux/trace.h>
1876a598ecSMasami Hiramatsu #include <linux/trace_events.h>
199c5b9d3dSMasami Hiramatsu 
209c5b9d3dSMasami Hiramatsu #include "trace.h"
219c5b9d3dSMasami Hiramatsu 
229c5b9d3dSMasami Hiramatsu #define MAX_BUF_LEN 256
239c5b9d3dSMasami Hiramatsu 
249c5b9d3dSMasami Hiramatsu static void __init
trace_boot_set_instance_options(struct trace_array * tr,struct xbc_node * node)254f712a4dSMasami Hiramatsu trace_boot_set_instance_options(struct trace_array *tr, struct xbc_node *node)
269c5b9d3dSMasami Hiramatsu {
279c5b9d3dSMasami Hiramatsu 	struct xbc_node *anode;
289c5b9d3dSMasami Hiramatsu 	const char *p;
299c5b9d3dSMasami Hiramatsu 	char buf[MAX_BUF_LEN];
309c5b9d3dSMasami Hiramatsu 	unsigned long v = 0;
319c5b9d3dSMasami Hiramatsu 
329c5b9d3dSMasami Hiramatsu 	/* Common ftrace options */
339c5b9d3dSMasami Hiramatsu 	xbc_node_for_each_array_value(node, "options", anode, p) {
34*fddca7dbSSteven Rostedt (Google) 		if (strscpy(buf, p, ARRAY_SIZE(buf)) < 0) {
359c5b9d3dSMasami Hiramatsu 			pr_err("String is too long: %s\n", p);
369c5b9d3dSMasami Hiramatsu 			continue;
379c5b9d3dSMasami Hiramatsu 		}
389c5b9d3dSMasami Hiramatsu 
399c5b9d3dSMasami Hiramatsu 		if (trace_set_options(tr, buf) < 0)
409c5b9d3dSMasami Hiramatsu 			pr_err("Failed to set option: %s\n", buf);
419c5b9d3dSMasami Hiramatsu 	}
429c5b9d3dSMasami Hiramatsu 
438490db06SMasami Hiramatsu 	p = xbc_node_find_value(node, "tracing_on", NULL);
448490db06SMasami Hiramatsu 	if (p && *p != '\0') {
458490db06SMasami Hiramatsu 		if (kstrtoul(p, 10, &v))
468490db06SMasami Hiramatsu 			pr_err("Failed to set tracing on: %s\n", p);
478490db06SMasami Hiramatsu 		if (v)
488490db06SMasami Hiramatsu 			tracer_tracing_on(tr);
498490db06SMasami Hiramatsu 		else
508490db06SMasami Hiramatsu 			tracer_tracing_off(tr);
518490db06SMasami Hiramatsu 	}
528490db06SMasami Hiramatsu 
539c5b9d3dSMasami Hiramatsu 	p = xbc_node_find_value(node, "trace_clock", NULL);
549c5b9d3dSMasami Hiramatsu 	if (p && *p != '\0') {
559c5b9d3dSMasami Hiramatsu 		if (tracing_set_clock(tr, p) < 0)
569c5b9d3dSMasami Hiramatsu 			pr_err("Failed to set trace clock: %s\n", p);
579c5b9d3dSMasami Hiramatsu 	}
589c5b9d3dSMasami Hiramatsu 
599c5b9d3dSMasami Hiramatsu 	p = xbc_node_find_value(node, "buffer_size", NULL);
609c5b9d3dSMasami Hiramatsu 	if (p && *p != '\0') {
619c5b9d3dSMasami Hiramatsu 		v = memparse(p, NULL);
629c5b9d3dSMasami Hiramatsu 		if (v < PAGE_SIZE)
639c5b9d3dSMasami Hiramatsu 			pr_err("Buffer size is too small: %s\n", p);
649c5b9d3dSMasami Hiramatsu 		if (tracing_resize_ring_buffer(tr, v, RING_BUFFER_ALL_CPUS) < 0)
659c5b9d3dSMasami Hiramatsu 			pr_err("Failed to resize trace buffer to %s\n", p);
669c5b9d3dSMasami Hiramatsu 	}
679d15dbbdSMasami Hiramatsu 
689d15dbbdSMasami Hiramatsu 	p = xbc_node_find_value(node, "cpumask", NULL);
699d15dbbdSMasami Hiramatsu 	if (p && *p != '\0') {
709d15dbbdSMasami Hiramatsu 		cpumask_var_t new_mask;
719d15dbbdSMasami Hiramatsu 
729d15dbbdSMasami Hiramatsu 		if (alloc_cpumask_var(&new_mask, GFP_KERNEL)) {
739d15dbbdSMasami Hiramatsu 			if (cpumask_parse(p, new_mask) < 0 ||
749d15dbbdSMasami Hiramatsu 			    tracing_set_cpumask(tr, new_mask) < 0)
759d15dbbdSMasami Hiramatsu 				pr_err("Failed to set new CPU mask %s\n", p);
769d15dbbdSMasami Hiramatsu 			free_cpumask_var(new_mask);
779d15dbbdSMasami Hiramatsu 		}
789d15dbbdSMasami Hiramatsu 	}
799c5b9d3dSMasami Hiramatsu }
809c5b9d3dSMasami Hiramatsu 
819c5b9d3dSMasami Hiramatsu #ifdef CONFIG_EVENT_TRACING
829c5b9d3dSMasami Hiramatsu static void __init
trace_boot_enable_events(struct trace_array * tr,struct xbc_node * node)839c5b9d3dSMasami Hiramatsu trace_boot_enable_events(struct trace_array *tr, struct xbc_node *node)
849c5b9d3dSMasami Hiramatsu {
859c5b9d3dSMasami Hiramatsu 	struct xbc_node *anode;
869c5b9d3dSMasami Hiramatsu 	char buf[MAX_BUF_LEN];
879c5b9d3dSMasami Hiramatsu 	const char *p;
889c5b9d3dSMasami Hiramatsu 
899c5b9d3dSMasami Hiramatsu 	xbc_node_for_each_array_value(node, "events", anode, p) {
90*fddca7dbSSteven Rostedt (Google) 		if (strscpy(buf, p, ARRAY_SIZE(buf)) < 0) {
919c5b9d3dSMasami Hiramatsu 			pr_err("String is too long: %s\n", p);
929c5b9d3dSMasami Hiramatsu 			continue;
939c5b9d3dSMasami Hiramatsu 		}
949c5b9d3dSMasami Hiramatsu 
959c5b9d3dSMasami Hiramatsu 		if (ftrace_set_clr_event(tr, buf, 1) < 0)
969c5b9d3dSMasami Hiramatsu 			pr_err("Failed to enable event: %s\n", p);
979c5b9d3dSMasami Hiramatsu 	}
989c5b9d3dSMasami Hiramatsu }
9981a59555SMasami Hiramatsu 
1004d655281SMasami Hiramatsu #ifdef CONFIG_KPROBE_EVENTS
1014d655281SMasami Hiramatsu static int __init
trace_boot_add_kprobe_event(struct xbc_node * node,const char * event)1024d655281SMasami Hiramatsu trace_boot_add_kprobe_event(struct xbc_node *node, const char *event)
1034d655281SMasami Hiramatsu {
10429a15481STom Zanussi 	struct dynevent_cmd cmd;
1054d655281SMasami Hiramatsu 	struct xbc_node *anode;
1064d655281SMasami Hiramatsu 	char buf[MAX_BUF_LEN];
1074d655281SMasami Hiramatsu 	const char *val;
108da0f1f41SMasami Hiramatsu 	int ret = 0;
1094d655281SMasami Hiramatsu 
1104d655281SMasami Hiramatsu 	xbc_node_for_each_array_value(node, "probes", anode, val) {
111da0f1f41SMasami Hiramatsu 		kprobe_event_cmd_init(&cmd, buf, MAX_BUF_LEN);
112da0f1f41SMasami Hiramatsu 
113da0f1f41SMasami Hiramatsu 		ret = kprobe_event_gen_cmd_start(&cmd, event, val);
11420dc3847SSascha Ortmann 		if (ret) {
11520dc3847SSascha Ortmann 			pr_err("Failed to generate probe: %s\n", buf);
116da0f1f41SMasami Hiramatsu 			break;
11720dc3847SSascha Ortmann 		}
1184d655281SMasami Hiramatsu 
11929a15481STom Zanussi 		ret = kprobe_event_gen_cmd_end(&cmd);
12020dc3847SSascha Ortmann 		if (ret) {
12129a15481STom Zanussi 			pr_err("Failed to add probe: %s\n", buf);
12220dc3847SSascha Ortmann 			break;
12320dc3847SSascha Ortmann 		}
124da0f1f41SMasami Hiramatsu 	}
12529a15481STom Zanussi 
12629a15481STom Zanussi 	return ret;
1274d655281SMasami Hiramatsu }
1284d655281SMasami Hiramatsu #else
1294d655281SMasami Hiramatsu static inline int __init
trace_boot_add_kprobe_event(struct xbc_node * node,const char * event)1304d655281SMasami Hiramatsu trace_boot_add_kprobe_event(struct xbc_node *node, const char *event)
1314d655281SMasami Hiramatsu {
1324d655281SMasami Hiramatsu 	pr_err("Kprobe event is not supported.\n");
1334d655281SMasami Hiramatsu 	return -ENOTSUPP;
1344d655281SMasami Hiramatsu }
1354d655281SMasami Hiramatsu #endif
1364d655281SMasami Hiramatsu 
1376c95503cSMasami Hiramatsu #ifdef CONFIG_SYNTH_EVENTS
1383fbe2d6eSMasami Hiramatsu static int __init
trace_boot_add_synth_event(struct xbc_node * node,const char * event)1393fbe2d6eSMasami Hiramatsu trace_boot_add_synth_event(struct xbc_node *node, const char *event)
1403fbe2d6eSMasami Hiramatsu {
141fdeb1acaSTom Zanussi 	struct dynevent_cmd cmd;
1423fbe2d6eSMasami Hiramatsu 	struct xbc_node *anode;
143fdeb1acaSTom Zanussi 	char buf[MAX_BUF_LEN];
1443fbe2d6eSMasami Hiramatsu 	const char *p;
145fdeb1acaSTom Zanussi 	int ret;
1463fbe2d6eSMasami Hiramatsu 
147fdeb1acaSTom Zanussi 	synth_event_cmd_init(&cmd, buf, MAX_BUF_LEN);
148fdeb1acaSTom Zanussi 
149fdeb1acaSTom Zanussi 	ret = synth_event_gen_cmd_start(&cmd, event, NULL);
150fdeb1acaSTom Zanussi 	if (ret)
151fdeb1acaSTom Zanussi 		return ret;
1523fbe2d6eSMasami Hiramatsu 
1533fbe2d6eSMasami Hiramatsu 	xbc_node_for_each_array_value(node, "fields", anode, p) {
154fdeb1acaSTom Zanussi 		ret = synth_event_add_field_str(&cmd, p);
155fdeb1acaSTom Zanussi 		if (ret)
156fdeb1acaSTom Zanussi 			return ret;
1573fbe2d6eSMasami Hiramatsu 	}
1583fbe2d6eSMasami Hiramatsu 
159fdeb1acaSTom Zanussi 	ret = synth_event_gen_cmd_end(&cmd);
1603fbe2d6eSMasami Hiramatsu 	if (ret < 0)
1613fbe2d6eSMasami Hiramatsu 		pr_err("Failed to add synthetic event: %s\n", buf);
1623fbe2d6eSMasami Hiramatsu 
1633fbe2d6eSMasami Hiramatsu 	return ret;
1643fbe2d6eSMasami Hiramatsu }
1653fbe2d6eSMasami Hiramatsu #else
1663fbe2d6eSMasami Hiramatsu static inline int __init
trace_boot_add_synth_event(struct xbc_node * node,const char * event)1673fbe2d6eSMasami Hiramatsu trace_boot_add_synth_event(struct xbc_node *node, const char *event)
1683fbe2d6eSMasami Hiramatsu {
1693fbe2d6eSMasami Hiramatsu 	pr_err("Synthetic event is not supported.\n");
1703fbe2d6eSMasami Hiramatsu 	return -ENOTSUPP;
1713fbe2d6eSMasami Hiramatsu }
1723fbe2d6eSMasami Hiramatsu #endif
1733fbe2d6eSMasami Hiramatsu 
174e66ed86cSMasami Hiramatsu #ifdef CONFIG_HIST_TRIGGERS
175e66ed86cSMasami Hiramatsu static int __init __printf(3, 4)
append_printf(char ** bufp,char * end,const char * fmt,...)176e66ed86cSMasami Hiramatsu append_printf(char **bufp, char *end, const char *fmt, ...)
177e66ed86cSMasami Hiramatsu {
178e66ed86cSMasami Hiramatsu 	va_list args;
179e66ed86cSMasami Hiramatsu 	int ret;
180e66ed86cSMasami Hiramatsu 
181e66ed86cSMasami Hiramatsu 	if (*bufp == end)
182e66ed86cSMasami Hiramatsu 		return -ENOSPC;
183e66ed86cSMasami Hiramatsu 
184e66ed86cSMasami Hiramatsu 	va_start(args, fmt);
185e66ed86cSMasami Hiramatsu 	ret = vsnprintf(*bufp, end - *bufp, fmt, args);
186e66ed86cSMasami Hiramatsu 	if (ret < end - *bufp) {
187e66ed86cSMasami Hiramatsu 		*bufp += ret;
188e66ed86cSMasami Hiramatsu 	} else {
189e66ed86cSMasami Hiramatsu 		*bufp = end;
190e66ed86cSMasami Hiramatsu 		ret = -ERANGE;
191e66ed86cSMasami Hiramatsu 	}
192e66ed86cSMasami Hiramatsu 	va_end(args);
193e66ed86cSMasami Hiramatsu 
194e66ed86cSMasami Hiramatsu 	return ret;
195e66ed86cSMasami Hiramatsu }
196e66ed86cSMasami Hiramatsu 
197e66ed86cSMasami Hiramatsu static int __init
append_str_nospace(char ** bufp,char * end,const char * str)198e66ed86cSMasami Hiramatsu append_str_nospace(char **bufp, char *end, const char *str)
199e66ed86cSMasami Hiramatsu {
200e66ed86cSMasami Hiramatsu 	char *p = *bufp;
201e66ed86cSMasami Hiramatsu 	int len;
202e66ed86cSMasami Hiramatsu 
203e66ed86cSMasami Hiramatsu 	while (p < end - 1 && *str != '\0') {
204e66ed86cSMasami Hiramatsu 		if (!isspace(*str))
205e66ed86cSMasami Hiramatsu 			*(p++) = *str;
206e66ed86cSMasami Hiramatsu 		str++;
207e66ed86cSMasami Hiramatsu 	}
208e66ed86cSMasami Hiramatsu 	*p = '\0';
209e66ed86cSMasami Hiramatsu 	if (p == end - 1) {
210e66ed86cSMasami Hiramatsu 		*bufp = end;
211e66ed86cSMasami Hiramatsu 		return -ENOSPC;
212e66ed86cSMasami Hiramatsu 	}
213e66ed86cSMasami Hiramatsu 	len = p - *bufp;
214e66ed86cSMasami Hiramatsu 	*bufp = p;
215e66ed86cSMasami Hiramatsu 	return (int)len;
216e66ed86cSMasami Hiramatsu }
217e66ed86cSMasami Hiramatsu 
218e66ed86cSMasami Hiramatsu static int __init
trace_boot_hist_add_array(struct xbc_node * hnode,char ** bufp,char * end,const char * key)219e66ed86cSMasami Hiramatsu trace_boot_hist_add_array(struct xbc_node *hnode, char **bufp,
220e66ed86cSMasami Hiramatsu 			  char *end, const char *key)
221e66ed86cSMasami Hiramatsu {
222a3928f87SMasami Hiramatsu 	struct xbc_node *anode;
223e66ed86cSMasami Hiramatsu 	const char *p;
224e66ed86cSMasami Hiramatsu 	char sep;
225e66ed86cSMasami Hiramatsu 
226a3928f87SMasami Hiramatsu 	p = xbc_node_find_value(hnode, key, &anode);
227a3928f87SMasami Hiramatsu 	if (p) {
228e66ed86cSMasami Hiramatsu 		if (!anode) {
229e66ed86cSMasami Hiramatsu 			pr_err("hist.%s requires value(s).\n", key);
230e66ed86cSMasami Hiramatsu 			return -EINVAL;
231e66ed86cSMasami Hiramatsu 		}
232e66ed86cSMasami Hiramatsu 
233e66ed86cSMasami Hiramatsu 		append_printf(bufp, end, ":%s", key);
234e66ed86cSMasami Hiramatsu 		sep = '=';
235e66ed86cSMasami Hiramatsu 		xbc_array_for_each_value(anode, p) {
236e66ed86cSMasami Hiramatsu 			append_printf(bufp, end, "%c%s", sep, p);
237e66ed86cSMasami Hiramatsu 			if (sep == '=')
238e66ed86cSMasami Hiramatsu 				sep = ',';
239e66ed86cSMasami Hiramatsu 		}
240e66ed86cSMasami Hiramatsu 	} else
241e66ed86cSMasami Hiramatsu 		return -ENOENT;
242e66ed86cSMasami Hiramatsu 
243e66ed86cSMasami Hiramatsu 	return 0;
244e66ed86cSMasami Hiramatsu }
245e66ed86cSMasami Hiramatsu 
246e66ed86cSMasami Hiramatsu static int __init
trace_boot_hist_add_one_handler(struct xbc_node * hnode,char ** bufp,char * end,const char * handler,const char * param)2478993665aSMasami Hiramatsu trace_boot_hist_add_one_handler(struct xbc_node *hnode, char **bufp,
2488993665aSMasami Hiramatsu 				char *end, const char *handler,
2498993665aSMasami Hiramatsu 				const char *param)
250e66ed86cSMasami Hiramatsu {
251e66ed86cSMasami Hiramatsu 	struct xbc_node *knode, *anode;
252e66ed86cSMasami Hiramatsu 	const char *p;
253e66ed86cSMasami Hiramatsu 	char sep;
254e66ed86cSMasami Hiramatsu 
255e66ed86cSMasami Hiramatsu 	/* Compose 'handler' parameter */
256e66ed86cSMasami Hiramatsu 	p = xbc_node_find_value(hnode, param, NULL);
257e66ed86cSMasami Hiramatsu 	if (!p) {
258e66ed86cSMasami Hiramatsu 		pr_err("hist.%s requires '%s' option.\n",
259e66ed86cSMasami Hiramatsu 		       xbc_node_get_data(hnode), param);
260e66ed86cSMasami Hiramatsu 		return -EINVAL;
261e66ed86cSMasami Hiramatsu 	}
2628993665aSMasami Hiramatsu 	append_printf(bufp, end, ":%s(%s)", handler, p);
263e66ed86cSMasami Hiramatsu 
264e66ed86cSMasami Hiramatsu 	/* Compose 'action' parameter */
2655dfe50b0SMasami Hiramatsu 	knode = xbc_node_find_subkey(hnode, "trace");
266e66ed86cSMasami Hiramatsu 	if (!knode)
2675dfe50b0SMasami Hiramatsu 		knode = xbc_node_find_subkey(hnode, "save");
268e66ed86cSMasami Hiramatsu 
269e66ed86cSMasami Hiramatsu 	if (knode) {
270e66ed86cSMasami Hiramatsu 		anode = xbc_node_get_child(knode);
271e66ed86cSMasami Hiramatsu 		if (!anode || !xbc_node_is_value(anode)) {
272e66ed86cSMasami Hiramatsu 			pr_err("hist.%s.%s requires value(s).\n",
273e66ed86cSMasami Hiramatsu 			       xbc_node_get_data(hnode),
274e66ed86cSMasami Hiramatsu 			       xbc_node_get_data(knode));
275e66ed86cSMasami Hiramatsu 			return -EINVAL;
276e66ed86cSMasami Hiramatsu 		}
277e66ed86cSMasami Hiramatsu 
278e66ed86cSMasami Hiramatsu 		append_printf(bufp, end, ".%s", xbc_node_get_data(knode));
279e66ed86cSMasami Hiramatsu 		sep = '(';
280e66ed86cSMasami Hiramatsu 		xbc_array_for_each_value(anode, p) {
281e66ed86cSMasami Hiramatsu 			append_printf(bufp, end, "%c%s", sep, p);
282e66ed86cSMasami Hiramatsu 			if (sep == '(')
283e66ed86cSMasami Hiramatsu 				sep = ',';
284e66ed86cSMasami Hiramatsu 		}
285e66ed86cSMasami Hiramatsu 		append_printf(bufp, end, ")");
2865dfe50b0SMasami Hiramatsu 	} else if (xbc_node_find_subkey(hnode, "snapshot")) {
287e66ed86cSMasami Hiramatsu 		append_printf(bufp, end, ".snapshot()");
288e66ed86cSMasami Hiramatsu 	} else {
289e66ed86cSMasami Hiramatsu 		pr_err("hist.%s requires an action.\n",
290e66ed86cSMasami Hiramatsu 		       xbc_node_get_data(hnode));
291e66ed86cSMasami Hiramatsu 		return -EINVAL;
292e66ed86cSMasami Hiramatsu 	}
293e66ed86cSMasami Hiramatsu 
294e66ed86cSMasami Hiramatsu 	return 0;
295e66ed86cSMasami Hiramatsu }
296e66ed86cSMasami Hiramatsu 
2978993665aSMasami Hiramatsu static int __init
trace_boot_hist_add_handlers(struct xbc_node * hnode,char ** bufp,char * end,const char * param)2988993665aSMasami Hiramatsu trace_boot_hist_add_handlers(struct xbc_node *hnode, char **bufp,
2998993665aSMasami Hiramatsu 			     char *end, const char *param)
3008993665aSMasami Hiramatsu {
3018993665aSMasami Hiramatsu 	struct xbc_node *node;
3028993665aSMasami Hiramatsu 	const char *p, *handler;
303154827f8SGautam Menghani 	int ret = 0;
3048993665aSMasami Hiramatsu 
3058993665aSMasami Hiramatsu 	handler = xbc_node_get_data(hnode);
3068993665aSMasami Hiramatsu 
3078993665aSMasami Hiramatsu 	xbc_node_for_each_subkey(hnode, node) {
3088993665aSMasami Hiramatsu 		p = xbc_node_get_data(node);
3098993665aSMasami Hiramatsu 		if (!isdigit(p[0]))
3108993665aSMasami Hiramatsu 			continue;
3118993665aSMasami Hiramatsu 		/* All digit started node should be instances. */
3128993665aSMasami Hiramatsu 		ret = trace_boot_hist_add_one_handler(node, bufp, end, handler, param);
3138993665aSMasami Hiramatsu 		if (ret < 0)
3148993665aSMasami Hiramatsu 			break;
3158993665aSMasami Hiramatsu 	}
3168993665aSMasami Hiramatsu 
3175dfe50b0SMasami Hiramatsu 	if (xbc_node_find_subkey(hnode, param))
3188993665aSMasami Hiramatsu 		ret = trace_boot_hist_add_one_handler(hnode, bufp, end, handler, param);
3198993665aSMasami Hiramatsu 
3208993665aSMasami Hiramatsu 	return ret;
3218993665aSMasami Hiramatsu }
3228993665aSMasami Hiramatsu 
323e66ed86cSMasami Hiramatsu /*
324e66ed86cSMasami Hiramatsu  * Histogram boottime tracing syntax.
325e66ed86cSMasami Hiramatsu  *
32617abd7c3SMasami Hiramatsu  * ftrace.[instance.INSTANCE.]event.GROUP.EVENT.hist[.N] {
327e66ed86cSMasami Hiramatsu  *	keys = <KEY>[,...]
328e66ed86cSMasami Hiramatsu  *	values = <VAL>[,...]
329e66ed86cSMasami Hiramatsu  *	sort = <SORT-KEY>[,...]
330e66ed86cSMasami Hiramatsu  *	size = <ENTRIES>
331e66ed86cSMasami Hiramatsu  *	name = <HISTNAME>
332e66ed86cSMasami Hiramatsu  *	var { <VAR> = <EXPR> ... }
333e66ed86cSMasami Hiramatsu  *	pause|continue|clear
3348993665aSMasami Hiramatsu  *	onmax|onchange[.N] { var = <VAR>; <ACTION> [= <PARAM>] }
3358993665aSMasami Hiramatsu  *	onmatch[.N] { event = <EVENT>; <ACTION> [= <PARAM>] }
336e66ed86cSMasami Hiramatsu  *	filter = <FILTER>
337e66ed86cSMasami Hiramatsu  * }
338e66ed86cSMasami Hiramatsu  *
339e66ed86cSMasami Hiramatsu  * Where <ACTION> are;
340e66ed86cSMasami Hiramatsu  *
341e66ed86cSMasami Hiramatsu  *	trace = <EVENT>, <ARG1>[, ...]
342e66ed86cSMasami Hiramatsu  *	save = <ARG1>[, ...]
343e66ed86cSMasami Hiramatsu  *	snapshot
344e66ed86cSMasami Hiramatsu  */
345e66ed86cSMasami Hiramatsu static int __init
trace_boot_compose_hist_cmd(struct xbc_node * hnode,char * buf,size_t size)346e66ed86cSMasami Hiramatsu trace_boot_compose_hist_cmd(struct xbc_node *hnode, char *buf, size_t size)
347e66ed86cSMasami Hiramatsu {
348e66ed86cSMasami Hiramatsu 	struct xbc_node *node, *knode;
349e66ed86cSMasami Hiramatsu 	char *end = buf + size;
350e66ed86cSMasami Hiramatsu 	const char *p;
351e66ed86cSMasami Hiramatsu 	int ret = 0;
352e66ed86cSMasami Hiramatsu 
353e66ed86cSMasami Hiramatsu 	append_printf(&buf, end, "hist");
354e66ed86cSMasami Hiramatsu 
355e66ed86cSMasami Hiramatsu 	ret = trace_boot_hist_add_array(hnode, &buf, end, "keys");
356e66ed86cSMasami Hiramatsu 	if (ret < 0) {
357e66ed86cSMasami Hiramatsu 		if (ret == -ENOENT)
358e66ed86cSMasami Hiramatsu 			pr_err("hist requires keys.\n");
359e66ed86cSMasami Hiramatsu 		return -EINVAL;
360e66ed86cSMasami Hiramatsu 	}
361e66ed86cSMasami Hiramatsu 
362e66ed86cSMasami Hiramatsu 	ret = trace_boot_hist_add_array(hnode, &buf, end, "values");
363e66ed86cSMasami Hiramatsu 	if (ret == -EINVAL)
364e66ed86cSMasami Hiramatsu 		return ret;
365e66ed86cSMasami Hiramatsu 	ret = trace_boot_hist_add_array(hnode, &buf, end, "sort");
366e66ed86cSMasami Hiramatsu 	if (ret == -EINVAL)
367e66ed86cSMasami Hiramatsu 		return ret;
368e66ed86cSMasami Hiramatsu 
369e66ed86cSMasami Hiramatsu 	p = xbc_node_find_value(hnode, "size", NULL);
370e66ed86cSMasami Hiramatsu 	if (p)
371e66ed86cSMasami Hiramatsu 		append_printf(&buf, end, ":size=%s", p);
372e66ed86cSMasami Hiramatsu 
373e66ed86cSMasami Hiramatsu 	p = xbc_node_find_value(hnode, "name", NULL);
374e66ed86cSMasami Hiramatsu 	if (p)
375e66ed86cSMasami Hiramatsu 		append_printf(&buf, end, ":name=%s", p);
376e66ed86cSMasami Hiramatsu 
3775dfe50b0SMasami Hiramatsu 	node = xbc_node_find_subkey(hnode, "var");
378e66ed86cSMasami Hiramatsu 	if (node) {
379e66ed86cSMasami Hiramatsu 		xbc_node_for_each_key_value(node, knode, p) {
380e66ed86cSMasami Hiramatsu 			/* Expression must not include spaces. */
381e66ed86cSMasami Hiramatsu 			append_printf(&buf, end, ":%s=",
382e66ed86cSMasami Hiramatsu 				      xbc_node_get_data(knode));
383e66ed86cSMasami Hiramatsu 			append_str_nospace(&buf, end, p);
384e66ed86cSMasami Hiramatsu 		}
385e66ed86cSMasami Hiramatsu 	}
386e66ed86cSMasami Hiramatsu 
387e66ed86cSMasami Hiramatsu 	/* Histogram control attributes (mutual exclusive) */
3885f8895b2SMasami Hiramatsu 	if (xbc_node_find_value(hnode, "pause", NULL))
389e66ed86cSMasami Hiramatsu 		append_printf(&buf, end, ":pause");
3905f8895b2SMasami Hiramatsu 	else if (xbc_node_find_value(hnode, "continue", NULL))
391e66ed86cSMasami Hiramatsu 		append_printf(&buf, end, ":continue");
3925f8895b2SMasami Hiramatsu 	else if (xbc_node_find_value(hnode, "clear", NULL))
393e66ed86cSMasami Hiramatsu 		append_printf(&buf, end, ":clear");
394e66ed86cSMasami Hiramatsu 
395e66ed86cSMasami Hiramatsu 	/* Histogram handler and actions */
3965dfe50b0SMasami Hiramatsu 	node = xbc_node_find_subkey(hnode, "onmax");
3978993665aSMasami Hiramatsu 	if (node && trace_boot_hist_add_handlers(node, &buf, end, "var") < 0)
398e66ed86cSMasami Hiramatsu 		return -EINVAL;
3995dfe50b0SMasami Hiramatsu 	node = xbc_node_find_subkey(hnode, "onchange");
4008993665aSMasami Hiramatsu 	if (node && trace_boot_hist_add_handlers(node, &buf, end, "var") < 0)
401e66ed86cSMasami Hiramatsu 		return -EINVAL;
4025dfe50b0SMasami Hiramatsu 	node = xbc_node_find_subkey(hnode, "onmatch");
4038993665aSMasami Hiramatsu 	if (node && trace_boot_hist_add_handlers(node, &buf, end, "event") < 0)
404e66ed86cSMasami Hiramatsu 		return -EINVAL;
405e66ed86cSMasami Hiramatsu 
406e66ed86cSMasami Hiramatsu 	p = xbc_node_find_value(hnode, "filter", NULL);
407e66ed86cSMasami Hiramatsu 	if (p)
408e66ed86cSMasami Hiramatsu 		append_printf(&buf, end, " if %s", p);
409e66ed86cSMasami Hiramatsu 
410e66ed86cSMasami Hiramatsu 	if (buf == end) {
411e66ed86cSMasami Hiramatsu 		pr_err("hist exceeds the max command length.\n");
412e66ed86cSMasami Hiramatsu 		return -E2BIG;
413e66ed86cSMasami Hiramatsu 	}
414e66ed86cSMasami Hiramatsu 
415e66ed86cSMasami Hiramatsu 	return 0;
416e66ed86cSMasami Hiramatsu }
41717abd7c3SMasami Hiramatsu 
41817abd7c3SMasami Hiramatsu static void __init
trace_boot_init_histograms(struct trace_event_file * file,struct xbc_node * hnode,char * buf,size_t size)41917abd7c3SMasami Hiramatsu trace_boot_init_histograms(struct trace_event_file *file,
42017abd7c3SMasami Hiramatsu 			   struct xbc_node *hnode, char *buf, size_t size)
421e66ed86cSMasami Hiramatsu {
42217abd7c3SMasami Hiramatsu 	struct xbc_node *node;
42317abd7c3SMasami Hiramatsu 	const char *p;
42464dc7f69SMasami Hiramatsu 	char *tmp;
42517abd7c3SMasami Hiramatsu 
42617abd7c3SMasami Hiramatsu 	xbc_node_for_each_subkey(hnode, node) {
42717abd7c3SMasami Hiramatsu 		p = xbc_node_get_data(node);
42817abd7c3SMasami Hiramatsu 		if (!isdigit(p[0]))
42917abd7c3SMasami Hiramatsu 			continue;
43017abd7c3SMasami Hiramatsu 		/* All digit started node should be instances. */
43117abd7c3SMasami Hiramatsu 		if (trace_boot_compose_hist_cmd(node, buf, size) == 0) {
43264dc7f69SMasami Hiramatsu 			tmp = kstrdup(buf, GFP_KERNEL);
4333c20bd3aSMathieu Desnoyers 			if (!tmp)
4343c20bd3aSMathieu Desnoyers 				return;
43517abd7c3SMasami Hiramatsu 			if (trigger_process_regex(file, buf) < 0)
43664dc7f69SMasami Hiramatsu 				pr_err("Failed to apply hist trigger: %s\n", tmp);
43764dc7f69SMasami Hiramatsu 			kfree(tmp);
43817abd7c3SMasami Hiramatsu 		}
43917abd7c3SMasami Hiramatsu 	}
44017abd7c3SMasami Hiramatsu 
4415dfe50b0SMasami Hiramatsu 	if (xbc_node_find_subkey(hnode, "keys")) {
44264dc7f69SMasami Hiramatsu 		if (trace_boot_compose_hist_cmd(hnode, buf, size) == 0) {
44364dc7f69SMasami Hiramatsu 			tmp = kstrdup(buf, GFP_KERNEL);
4443c20bd3aSMathieu Desnoyers 			if (!tmp)
4453c20bd3aSMathieu Desnoyers 				return;
44617abd7c3SMasami Hiramatsu 			if (trigger_process_regex(file, buf) < 0)
44764dc7f69SMasami Hiramatsu 				pr_err("Failed to apply hist trigger: %s\n", tmp);
44864dc7f69SMasami Hiramatsu 			kfree(tmp);
44964dc7f69SMasami Hiramatsu 		}
45017abd7c3SMasami Hiramatsu 	}
45117abd7c3SMasami Hiramatsu }
45217abd7c3SMasami Hiramatsu #else
45317abd7c3SMasami Hiramatsu static void __init
trace_boot_init_histograms(struct trace_event_file * file,struct xbc_node * hnode,char * buf,size_t size)45417abd7c3SMasami Hiramatsu trace_boot_init_histograms(struct trace_event_file *file,
45517abd7c3SMasami Hiramatsu 			   struct xbc_node *hnode, char *buf, size_t size)
45617abd7c3SMasami Hiramatsu {
45717abd7c3SMasami Hiramatsu 	/* do nothing */
458e66ed86cSMasami Hiramatsu }
459e66ed86cSMasami Hiramatsu #endif
460e66ed86cSMasami Hiramatsu 
46181a59555SMasami Hiramatsu static void __init
trace_boot_init_one_event(struct trace_array * tr,struct xbc_node * gnode,struct xbc_node * enode)46281a59555SMasami Hiramatsu trace_boot_init_one_event(struct trace_array *tr, struct xbc_node *gnode,
46381a59555SMasami Hiramatsu 			  struct xbc_node *enode)
46481a59555SMasami Hiramatsu {
46581a59555SMasami Hiramatsu 	struct trace_event_file *file;
46681a59555SMasami Hiramatsu 	struct xbc_node *anode;
46781a59555SMasami Hiramatsu 	char buf[MAX_BUF_LEN];
46881a59555SMasami Hiramatsu 	const char *p, *group, *event;
46981a59555SMasami Hiramatsu 
47081a59555SMasami Hiramatsu 	group = xbc_node_get_data(gnode);
47181a59555SMasami Hiramatsu 	event = xbc_node_get_data(enode);
47281a59555SMasami Hiramatsu 
4734d655281SMasami Hiramatsu 	if (!strcmp(group, "kprobes"))
4744d655281SMasami Hiramatsu 		if (trace_boot_add_kprobe_event(enode, event) < 0)
4754d655281SMasami Hiramatsu 			return;
4763fbe2d6eSMasami Hiramatsu 	if (!strcmp(group, "synthetic"))
4773fbe2d6eSMasami Hiramatsu 		if (trace_boot_add_synth_event(enode, event) < 0)
4783fbe2d6eSMasami Hiramatsu 			return;
4794d655281SMasami Hiramatsu 
48081a59555SMasami Hiramatsu 	mutex_lock(&event_mutex);
48181a59555SMasami Hiramatsu 	file = find_event_file(tr, group, event);
48281a59555SMasami Hiramatsu 	if (!file) {
48381a59555SMasami Hiramatsu 		pr_err("Failed to find event: %s:%s\n", group, event);
48481a59555SMasami Hiramatsu 		goto out;
48581a59555SMasami Hiramatsu 	}
48681a59555SMasami Hiramatsu 
48781a59555SMasami Hiramatsu 	p = xbc_node_find_value(enode, "filter", NULL);
48881a59555SMasami Hiramatsu 	if (p && *p != '\0') {
489*fddca7dbSSteven Rostedt (Google) 		if (strscpy(buf, p, ARRAY_SIZE(buf)) < 0)
49081a59555SMasami Hiramatsu 			pr_err("filter string is too long: %s\n", p);
49181a59555SMasami Hiramatsu 		else if (apply_event_filter(file, buf) < 0)
49281a59555SMasami Hiramatsu 			pr_err("Failed to apply filter: %s\n", buf);
49381a59555SMasami Hiramatsu 	}
49481a59555SMasami Hiramatsu 
4956fe7c745SMasami Hiramatsu 	if (IS_ENABLED(CONFIG_HIST_TRIGGERS)) {
49681a59555SMasami Hiramatsu 		xbc_node_for_each_array_value(enode, "actions", anode, p) {
497*fddca7dbSSteven Rostedt (Google) 			if (strscpy(buf, p, ARRAY_SIZE(buf)) < 0)
49881a59555SMasami Hiramatsu 				pr_err("action string is too long: %s\n", p);
49981a59555SMasami Hiramatsu 			else if (trigger_process_regex(file, buf) < 0)
50064dc7f69SMasami Hiramatsu 				pr_err("Failed to apply an action: %s\n", p);
50181a59555SMasami Hiramatsu 		}
5025dfe50b0SMasami Hiramatsu 		anode = xbc_node_find_subkey(enode, "hist");
50317abd7c3SMasami Hiramatsu 		if (anode)
50417abd7c3SMasami Hiramatsu 			trace_boot_init_histograms(file, anode, buf, ARRAY_SIZE(buf));
5056fe7c745SMasami Hiramatsu 	} else if (xbc_node_find_value(enode, "actions", NULL))
5066fe7c745SMasami Hiramatsu 		pr_err("Failed to apply event actions because CONFIG_HIST_TRIGGERS is not set.\n");
50781a59555SMasami Hiramatsu 
50881a59555SMasami Hiramatsu 	if (xbc_node_find_value(enode, "enable", NULL)) {
50981a59555SMasami Hiramatsu 		if (trace_event_enable_disable(file, 1, 0) < 0)
51081a59555SMasami Hiramatsu 			pr_err("Failed to enable event node: %s:%s\n",
51181a59555SMasami Hiramatsu 				group, event);
51281a59555SMasami Hiramatsu 	}
51381a59555SMasami Hiramatsu out:
51481a59555SMasami Hiramatsu 	mutex_unlock(&event_mutex);
51581a59555SMasami Hiramatsu }
51681a59555SMasami Hiramatsu 
51781a59555SMasami Hiramatsu static void __init
trace_boot_init_events(struct trace_array * tr,struct xbc_node * node)51881a59555SMasami Hiramatsu trace_boot_init_events(struct trace_array *tr, struct xbc_node *node)
51981a59555SMasami Hiramatsu {
52081a59555SMasami Hiramatsu 	struct xbc_node *gnode, *enode;
5214f99f848SMasami Hiramatsu 	bool enable, enable_all = false;
5224f99f848SMasami Hiramatsu 	const char *data;
52381a59555SMasami Hiramatsu 
5245dfe50b0SMasami Hiramatsu 	node = xbc_node_find_subkey(node, "event");
52581a59555SMasami Hiramatsu 	if (!node)
52681a59555SMasami Hiramatsu 		return;
52781a59555SMasami Hiramatsu 	/* per-event key starts with "event.GROUP.EVENT" */
528cfd79983SMasami Hiramatsu 	xbc_node_for_each_subkey(node, gnode) {
5294f99f848SMasami Hiramatsu 		data = xbc_node_get_data(gnode);
5304f99f848SMasami Hiramatsu 		if (!strcmp(data, "enable")) {
5314f99f848SMasami Hiramatsu 			enable_all = true;
5324f99f848SMasami Hiramatsu 			continue;
5334f99f848SMasami Hiramatsu 		}
5344f99f848SMasami Hiramatsu 		enable = false;
535cfd79983SMasami Hiramatsu 		xbc_node_for_each_subkey(gnode, enode) {
5364f99f848SMasami Hiramatsu 			data = xbc_node_get_data(enode);
5374f99f848SMasami Hiramatsu 			if (!strcmp(data, "enable")) {
5384f99f848SMasami Hiramatsu 				enable = true;
5394f99f848SMasami Hiramatsu 				continue;
5404f99f848SMasami Hiramatsu 			}
54181a59555SMasami Hiramatsu 			trace_boot_init_one_event(tr, gnode, enode);
54281a59555SMasami Hiramatsu 		}
5434f99f848SMasami Hiramatsu 		/* Event enablement must be done after event settings */
5444f99f848SMasami Hiramatsu 		if (enable) {
5454f99f848SMasami Hiramatsu 			data = xbc_node_get_data(gnode);
5464f99f848SMasami Hiramatsu 			trace_array_set_clr_event(tr, data, NULL, true);
5474f99f848SMasami Hiramatsu 		}
5484f99f848SMasami Hiramatsu 	}
5494f99f848SMasami Hiramatsu 	/* Ditto */
5504f99f848SMasami Hiramatsu 	if (enable_all)
5514f99f848SMasami Hiramatsu 		trace_array_set_clr_event(tr, NULL, NULL, true);
5524f99f848SMasami Hiramatsu }
5539c5b9d3dSMasami Hiramatsu #else
5549c5b9d3dSMasami Hiramatsu #define trace_boot_enable_events(tr, node) do {} while (0)
55581a59555SMasami Hiramatsu #define trace_boot_init_events(tr, node) do {} while (0)
5569c5b9d3dSMasami Hiramatsu #endif
5579c5b9d3dSMasami Hiramatsu 
558fe1efe92SMasami Hiramatsu #ifdef CONFIG_DYNAMIC_FTRACE
559fe1efe92SMasami Hiramatsu static void __init
trace_boot_set_ftrace_filter(struct trace_array * tr,struct xbc_node * node)560fe1efe92SMasami Hiramatsu trace_boot_set_ftrace_filter(struct trace_array *tr, struct xbc_node *node)
561fe1efe92SMasami Hiramatsu {
562fe1efe92SMasami Hiramatsu 	struct xbc_node *anode;
563fe1efe92SMasami Hiramatsu 	const char *p;
564fe1efe92SMasami Hiramatsu 	char *q;
565fe1efe92SMasami Hiramatsu 
566fe1efe92SMasami Hiramatsu 	xbc_node_for_each_array_value(node, "ftrace.filters", anode, p) {
567fe1efe92SMasami Hiramatsu 		q = kstrdup(p, GFP_KERNEL);
568fe1efe92SMasami Hiramatsu 		if (!q)
569fe1efe92SMasami Hiramatsu 			return;
570fe1efe92SMasami Hiramatsu 		if (ftrace_set_filter(tr->ops, q, strlen(q), 0) < 0)
571fe1efe92SMasami Hiramatsu 			pr_err("Failed to add %s to ftrace filter\n", p);
572fe1efe92SMasami Hiramatsu 		else
573fe1efe92SMasami Hiramatsu 			ftrace_filter_param = true;
574fe1efe92SMasami Hiramatsu 		kfree(q);
575fe1efe92SMasami Hiramatsu 	}
576fe1efe92SMasami Hiramatsu 	xbc_node_for_each_array_value(node, "ftrace.notraces", anode, p) {
577fe1efe92SMasami Hiramatsu 		q = kstrdup(p, GFP_KERNEL);
578fe1efe92SMasami Hiramatsu 		if (!q)
579fe1efe92SMasami Hiramatsu 			return;
580fe1efe92SMasami Hiramatsu 		if (ftrace_set_notrace(tr->ops, q, strlen(q), 0) < 0)
581fe1efe92SMasami Hiramatsu 			pr_err("Failed to add %s to ftrace filter\n", p);
582fe1efe92SMasami Hiramatsu 		else
583fe1efe92SMasami Hiramatsu 			ftrace_filter_param = true;
584fe1efe92SMasami Hiramatsu 		kfree(q);
585fe1efe92SMasami Hiramatsu 	}
586fe1efe92SMasami Hiramatsu }
587fe1efe92SMasami Hiramatsu #else
588fe1efe92SMasami Hiramatsu #define trace_boot_set_ftrace_filter(tr, node) do {} while (0)
589fe1efe92SMasami Hiramatsu #endif
590fe1efe92SMasami Hiramatsu 
5919c5b9d3dSMasami Hiramatsu static void __init
trace_boot_enable_tracer(struct trace_array * tr,struct xbc_node * node)5929c5b9d3dSMasami Hiramatsu trace_boot_enable_tracer(struct trace_array *tr, struct xbc_node *node)
5939c5b9d3dSMasami Hiramatsu {
5949c5b9d3dSMasami Hiramatsu 	const char *p;
5959c5b9d3dSMasami Hiramatsu 
596fe1efe92SMasami Hiramatsu 	trace_boot_set_ftrace_filter(tr, node);
597fe1efe92SMasami Hiramatsu 
5989c5b9d3dSMasami Hiramatsu 	p = xbc_node_find_value(node, "tracer", NULL);
5999c5b9d3dSMasami Hiramatsu 	if (p && *p != '\0') {
6009c5b9d3dSMasami Hiramatsu 		if (tracing_set_tracer(tr, p) < 0)
6019c5b9d3dSMasami Hiramatsu 			pr_err("Failed to set given tracer: %s\n", p);
6029c5b9d3dSMasami Hiramatsu 	}
603c1634097SMasami Hiramatsu 
604c1634097SMasami Hiramatsu 	/* Since tracer can free snapshot buffer, allocate snapshot here.*/
605c1634097SMasami Hiramatsu 	if (xbc_node_find_value(node, "alloc_snapshot", NULL)) {
606c1634097SMasami Hiramatsu 		if (tracing_alloc_snapshot_instance(tr) < 0)
607c1634097SMasami Hiramatsu 			pr_err("Failed to allocate snapshot buffer\n");
608c1634097SMasami Hiramatsu 	}
6099c5b9d3dSMasami Hiramatsu }
6109c5b9d3dSMasami Hiramatsu 
6114f712a4dSMasami Hiramatsu static void __init
trace_boot_init_one_instance(struct trace_array * tr,struct xbc_node * node)6124f712a4dSMasami Hiramatsu trace_boot_init_one_instance(struct trace_array *tr, struct xbc_node *node)
6134f712a4dSMasami Hiramatsu {
6144f712a4dSMasami Hiramatsu 	trace_boot_set_instance_options(tr, node);
6154f712a4dSMasami Hiramatsu 	trace_boot_init_events(tr, node);
6164f712a4dSMasami Hiramatsu 	trace_boot_enable_events(tr, node);
6174f712a4dSMasami Hiramatsu 	trace_boot_enable_tracer(tr, node);
6184f712a4dSMasami Hiramatsu }
6194f712a4dSMasami Hiramatsu 
6204f712a4dSMasami Hiramatsu static void __init
trace_boot_init_instances(struct xbc_node * node)6214f712a4dSMasami Hiramatsu trace_boot_init_instances(struct xbc_node *node)
6224f712a4dSMasami Hiramatsu {
6234f712a4dSMasami Hiramatsu 	struct xbc_node *inode;
6244f712a4dSMasami Hiramatsu 	struct trace_array *tr;
6254f712a4dSMasami Hiramatsu 	const char *p;
6264f712a4dSMasami Hiramatsu 
6275dfe50b0SMasami Hiramatsu 	node = xbc_node_find_subkey(node, "instance");
6284f712a4dSMasami Hiramatsu 	if (!node)
6294f712a4dSMasami Hiramatsu 		return;
6304f712a4dSMasami Hiramatsu 
631cfd79983SMasami Hiramatsu 	xbc_node_for_each_subkey(node, inode) {
6324f712a4dSMasami Hiramatsu 		p = xbc_node_get_data(inode);
6334f712a4dSMasami Hiramatsu 		if (!p || *p == '\0')
6344f712a4dSMasami Hiramatsu 			continue;
6354f712a4dSMasami Hiramatsu 
6364f712a4dSMasami Hiramatsu 		tr = trace_array_get_by_name(p);
637532f49a6SDan Carpenter 		if (!tr) {
6384f712a4dSMasami Hiramatsu 			pr_err("Failed to get trace instance %s\n", p);
6394f712a4dSMasami Hiramatsu 			continue;
6404f712a4dSMasami Hiramatsu 		}
6414f712a4dSMasami Hiramatsu 		trace_boot_init_one_instance(tr, inode);
64228394da2SSteven Rostedt (VMware) 		trace_array_put(tr);
6434f712a4dSMasami Hiramatsu 	}
6444f712a4dSMasami Hiramatsu }
6454f712a4dSMasami Hiramatsu 
trace_boot_init(void)6469c5b9d3dSMasami Hiramatsu static int __init trace_boot_init(void)
6479c5b9d3dSMasami Hiramatsu {
6489c5b9d3dSMasami Hiramatsu 	struct xbc_node *trace_node;
6499c5b9d3dSMasami Hiramatsu 	struct trace_array *tr;
6509c5b9d3dSMasami Hiramatsu 
6519c5b9d3dSMasami Hiramatsu 	trace_node = xbc_find_node("ftrace");
6529c5b9d3dSMasami Hiramatsu 	if (!trace_node)
6539c5b9d3dSMasami Hiramatsu 		return 0;
6549c5b9d3dSMasami Hiramatsu 
6559c5b9d3dSMasami Hiramatsu 	tr = top_trace_array();
6569c5b9d3dSMasami Hiramatsu 	if (!tr)
6579c5b9d3dSMasami Hiramatsu 		return 0;
6589c5b9d3dSMasami Hiramatsu 
6594f712a4dSMasami Hiramatsu 	/* Global trace array is also one instance */
6604f712a4dSMasami Hiramatsu 	trace_boot_init_one_instance(tr, trace_node);
6614f712a4dSMasami Hiramatsu 	trace_boot_init_instances(trace_node);
6629c5b9d3dSMasami Hiramatsu 
66360efe21eSMasami Hiramatsu 	disable_tracing_selftest("running boot-time tracing");
66460efe21eSMasami Hiramatsu 
6659c5b9d3dSMasami Hiramatsu 	return 0;
6669c5b9d3dSMasami Hiramatsu }
667ba0fbfbbSMasami Hiramatsu /*
668ba0fbfbbSMasami Hiramatsu  * Start tracing at the end of core-initcall, so that it starts tracing
669ba0fbfbbSMasami Hiramatsu  * from the beginning of postcore_initcall.
670ba0fbfbbSMasami Hiramatsu  */
671ba0fbfbbSMasami Hiramatsu core_initcall_sync(trace_boot_init);
672