0001
0002
0003
0004
0005
0006
0007 #define pr_fmt(fmt) "trace_boot: " fmt
0008
0009 #include <linux/bootconfig.h>
0010 #include <linux/cpumask.h>
0011 #include <linux/ftrace.h>
0012 #include <linux/init.h>
0013 #include <linux/kernel.h>
0014 #include <linux/mutex.h>
0015 #include <linux/string.h>
0016 #include <linux/slab.h>
0017 #include <linux/trace.h>
0018 #include <linux/trace_events.h>
0019
0020 #include "trace.h"
0021
0022 #define MAX_BUF_LEN 256
0023
0024 static void __init
0025 trace_boot_set_instance_options(struct trace_array *tr, struct xbc_node *node)
0026 {
0027 struct xbc_node *anode;
0028 const char *p;
0029 char buf[MAX_BUF_LEN];
0030 unsigned long v = 0;
0031
0032
0033 xbc_node_for_each_array_value(node, "options", anode, p) {
0034 if (strlcpy(buf, p, ARRAY_SIZE(buf)) >= ARRAY_SIZE(buf)) {
0035 pr_err("String is too long: %s\n", p);
0036 continue;
0037 }
0038
0039 if (trace_set_options(tr, buf) < 0)
0040 pr_err("Failed to set option: %s\n", buf);
0041 }
0042
0043 p = xbc_node_find_value(node, "tracing_on", NULL);
0044 if (p && *p != '\0') {
0045 if (kstrtoul(p, 10, &v))
0046 pr_err("Failed to set tracing on: %s\n", p);
0047 if (v)
0048 tracer_tracing_on(tr);
0049 else
0050 tracer_tracing_off(tr);
0051 }
0052
0053 p = xbc_node_find_value(node, "trace_clock", NULL);
0054 if (p && *p != '\0') {
0055 if (tracing_set_clock(tr, p) < 0)
0056 pr_err("Failed to set trace clock: %s\n", p);
0057 }
0058
0059 p = xbc_node_find_value(node, "buffer_size", NULL);
0060 if (p && *p != '\0') {
0061 v = memparse(p, NULL);
0062 if (v < PAGE_SIZE)
0063 pr_err("Buffer size is too small: %s\n", p);
0064 if (tracing_resize_ring_buffer(tr, v, RING_BUFFER_ALL_CPUS) < 0)
0065 pr_err("Failed to resize trace buffer to %s\n", p);
0066 }
0067
0068 p = xbc_node_find_value(node, "cpumask", NULL);
0069 if (p && *p != '\0') {
0070 cpumask_var_t new_mask;
0071
0072 if (alloc_cpumask_var(&new_mask, GFP_KERNEL)) {
0073 if (cpumask_parse(p, new_mask) < 0 ||
0074 tracing_set_cpumask(tr, new_mask) < 0)
0075 pr_err("Failed to set new CPU mask %s\n", p);
0076 free_cpumask_var(new_mask);
0077 }
0078 }
0079 }
0080
0081 #ifdef CONFIG_EVENT_TRACING
0082 static void __init
0083 trace_boot_enable_events(struct trace_array *tr, struct xbc_node *node)
0084 {
0085 struct xbc_node *anode;
0086 char buf[MAX_BUF_LEN];
0087 const char *p;
0088
0089 xbc_node_for_each_array_value(node, "events", anode, p) {
0090 if (strlcpy(buf, p, ARRAY_SIZE(buf)) >= ARRAY_SIZE(buf)) {
0091 pr_err("String is too long: %s\n", p);
0092 continue;
0093 }
0094
0095 if (ftrace_set_clr_event(tr, buf, 1) < 0)
0096 pr_err("Failed to enable event: %s\n", p);
0097 }
0098 }
0099
0100 #ifdef CONFIG_KPROBE_EVENTS
0101 static int __init
0102 trace_boot_add_kprobe_event(struct xbc_node *node, const char *event)
0103 {
0104 struct dynevent_cmd cmd;
0105 struct xbc_node *anode;
0106 char buf[MAX_BUF_LEN];
0107 const char *val;
0108 int ret = 0;
0109
0110 xbc_node_for_each_array_value(node, "probes", anode, val) {
0111 kprobe_event_cmd_init(&cmd, buf, MAX_BUF_LEN);
0112
0113 ret = kprobe_event_gen_cmd_start(&cmd, event, val);
0114 if (ret) {
0115 pr_err("Failed to generate probe: %s\n", buf);
0116 break;
0117 }
0118
0119 ret = kprobe_event_gen_cmd_end(&cmd);
0120 if (ret) {
0121 pr_err("Failed to add probe: %s\n", buf);
0122 break;
0123 }
0124 }
0125
0126 return ret;
0127 }
0128 #else
0129 static inline int __init
0130 trace_boot_add_kprobe_event(struct xbc_node *node, const char *event)
0131 {
0132 pr_err("Kprobe event is not supported.\n");
0133 return -ENOTSUPP;
0134 }
0135 #endif
0136
0137 #ifdef CONFIG_SYNTH_EVENTS
0138 static int __init
0139 trace_boot_add_synth_event(struct xbc_node *node, const char *event)
0140 {
0141 struct dynevent_cmd cmd;
0142 struct xbc_node *anode;
0143 char buf[MAX_BUF_LEN];
0144 const char *p;
0145 int ret;
0146
0147 synth_event_cmd_init(&cmd, buf, MAX_BUF_LEN);
0148
0149 ret = synth_event_gen_cmd_start(&cmd, event, NULL);
0150 if (ret)
0151 return ret;
0152
0153 xbc_node_for_each_array_value(node, "fields", anode, p) {
0154 ret = synth_event_add_field_str(&cmd, p);
0155 if (ret)
0156 return ret;
0157 }
0158
0159 ret = synth_event_gen_cmd_end(&cmd);
0160 if (ret < 0)
0161 pr_err("Failed to add synthetic event: %s\n", buf);
0162
0163 return ret;
0164 }
0165 #else
0166 static inline int __init
0167 trace_boot_add_synth_event(struct xbc_node *node, const char *event)
0168 {
0169 pr_err("Synthetic event is not supported.\n");
0170 return -ENOTSUPP;
0171 }
0172 #endif
0173
0174 #ifdef CONFIG_HIST_TRIGGERS
0175 static int __init __printf(3, 4)
0176 append_printf(char **bufp, char *end, const char *fmt, ...)
0177 {
0178 va_list args;
0179 int ret;
0180
0181 if (*bufp == end)
0182 return -ENOSPC;
0183
0184 va_start(args, fmt);
0185 ret = vsnprintf(*bufp, end - *bufp, fmt, args);
0186 if (ret < end - *bufp) {
0187 *bufp += ret;
0188 } else {
0189 *bufp = end;
0190 ret = -ERANGE;
0191 }
0192 va_end(args);
0193
0194 return ret;
0195 }
0196
0197 static int __init
0198 append_str_nospace(char **bufp, char *end, const char *str)
0199 {
0200 char *p = *bufp;
0201 int len;
0202
0203 while (p < end - 1 && *str != '\0') {
0204 if (!isspace(*str))
0205 *(p++) = *str;
0206 str++;
0207 }
0208 *p = '\0';
0209 if (p == end - 1) {
0210 *bufp = end;
0211 return -ENOSPC;
0212 }
0213 len = p - *bufp;
0214 *bufp = p;
0215 return (int)len;
0216 }
0217
0218 static int __init
0219 trace_boot_hist_add_array(struct xbc_node *hnode, char **bufp,
0220 char *end, const char *key)
0221 {
0222 struct xbc_node *anode;
0223 const char *p;
0224 char sep;
0225
0226 p = xbc_node_find_value(hnode, key, &anode);
0227 if (p) {
0228 if (!anode) {
0229 pr_err("hist.%s requires value(s).\n", key);
0230 return -EINVAL;
0231 }
0232
0233 append_printf(bufp, end, ":%s", key);
0234 sep = '=';
0235 xbc_array_for_each_value(anode, p) {
0236 append_printf(bufp, end, "%c%s", sep, p);
0237 if (sep == '=')
0238 sep = ',';
0239 }
0240 } else
0241 return -ENOENT;
0242
0243 return 0;
0244 }
0245
0246 static int __init
0247 trace_boot_hist_add_one_handler(struct xbc_node *hnode, char **bufp,
0248 char *end, const char *handler,
0249 const char *param)
0250 {
0251 struct xbc_node *knode, *anode;
0252 const char *p;
0253 char sep;
0254
0255
0256 p = xbc_node_find_value(hnode, param, NULL);
0257 if (!p) {
0258 pr_err("hist.%s requires '%s' option.\n",
0259 xbc_node_get_data(hnode), param);
0260 return -EINVAL;
0261 }
0262 append_printf(bufp, end, ":%s(%s)", handler, p);
0263
0264
0265 knode = xbc_node_find_subkey(hnode, "trace");
0266 if (!knode)
0267 knode = xbc_node_find_subkey(hnode, "save");
0268
0269 if (knode) {
0270 anode = xbc_node_get_child(knode);
0271 if (!anode || !xbc_node_is_value(anode)) {
0272 pr_err("hist.%s.%s requires value(s).\n",
0273 xbc_node_get_data(hnode),
0274 xbc_node_get_data(knode));
0275 return -EINVAL;
0276 }
0277
0278 append_printf(bufp, end, ".%s", xbc_node_get_data(knode));
0279 sep = '(';
0280 xbc_array_for_each_value(anode, p) {
0281 append_printf(bufp, end, "%c%s", sep, p);
0282 if (sep == '(')
0283 sep = ',';
0284 }
0285 append_printf(bufp, end, ")");
0286 } else if (xbc_node_find_subkey(hnode, "snapshot")) {
0287 append_printf(bufp, end, ".snapshot()");
0288 } else {
0289 pr_err("hist.%s requires an action.\n",
0290 xbc_node_get_data(hnode));
0291 return -EINVAL;
0292 }
0293
0294 return 0;
0295 }
0296
0297 static int __init
0298 trace_boot_hist_add_handlers(struct xbc_node *hnode, char **bufp,
0299 char *end, const char *param)
0300 {
0301 struct xbc_node *node;
0302 const char *p, *handler;
0303 int ret = 0;
0304
0305 handler = xbc_node_get_data(hnode);
0306
0307 xbc_node_for_each_subkey(hnode, node) {
0308 p = xbc_node_get_data(node);
0309 if (!isdigit(p[0]))
0310 continue;
0311
0312 ret = trace_boot_hist_add_one_handler(node, bufp, end, handler, param);
0313 if (ret < 0)
0314 break;
0315 }
0316
0317 if (xbc_node_find_subkey(hnode, param))
0318 ret = trace_boot_hist_add_one_handler(hnode, bufp, end, handler, param);
0319
0320 return ret;
0321 }
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345 static int __init
0346 trace_boot_compose_hist_cmd(struct xbc_node *hnode, char *buf, size_t size)
0347 {
0348 struct xbc_node *node, *knode;
0349 char *end = buf + size;
0350 const char *p;
0351 int ret = 0;
0352
0353 append_printf(&buf, end, "hist");
0354
0355 ret = trace_boot_hist_add_array(hnode, &buf, end, "keys");
0356 if (ret < 0) {
0357 if (ret == -ENOENT)
0358 pr_err("hist requires keys.\n");
0359 return -EINVAL;
0360 }
0361
0362 ret = trace_boot_hist_add_array(hnode, &buf, end, "values");
0363 if (ret == -EINVAL)
0364 return ret;
0365 ret = trace_boot_hist_add_array(hnode, &buf, end, "sort");
0366 if (ret == -EINVAL)
0367 return ret;
0368
0369 p = xbc_node_find_value(hnode, "size", NULL);
0370 if (p)
0371 append_printf(&buf, end, ":size=%s", p);
0372
0373 p = xbc_node_find_value(hnode, "name", NULL);
0374 if (p)
0375 append_printf(&buf, end, ":name=%s", p);
0376
0377 node = xbc_node_find_subkey(hnode, "var");
0378 if (node) {
0379 xbc_node_for_each_key_value(node, knode, p) {
0380
0381 append_printf(&buf, end, ":%s=",
0382 xbc_node_get_data(knode));
0383 append_str_nospace(&buf, end, p);
0384 }
0385 }
0386
0387
0388 if (xbc_node_find_value(hnode, "pause", NULL))
0389 append_printf(&buf, end, ":pause");
0390 else if (xbc_node_find_value(hnode, "continue", NULL))
0391 append_printf(&buf, end, ":continue");
0392 else if (xbc_node_find_value(hnode, "clear", NULL))
0393 append_printf(&buf, end, ":clear");
0394
0395
0396 node = xbc_node_find_subkey(hnode, "onmax");
0397 if (node && trace_boot_hist_add_handlers(node, &buf, end, "var") < 0)
0398 return -EINVAL;
0399 node = xbc_node_find_subkey(hnode, "onchange");
0400 if (node && trace_boot_hist_add_handlers(node, &buf, end, "var") < 0)
0401 return -EINVAL;
0402 node = xbc_node_find_subkey(hnode, "onmatch");
0403 if (node && trace_boot_hist_add_handlers(node, &buf, end, "event") < 0)
0404 return -EINVAL;
0405
0406 p = xbc_node_find_value(hnode, "filter", NULL);
0407 if (p)
0408 append_printf(&buf, end, " if %s", p);
0409
0410 if (buf == end) {
0411 pr_err("hist exceeds the max command length.\n");
0412 return -E2BIG;
0413 }
0414
0415 return 0;
0416 }
0417
0418 static void __init
0419 trace_boot_init_histograms(struct trace_event_file *file,
0420 struct xbc_node *hnode, char *buf, size_t size)
0421 {
0422 struct xbc_node *node;
0423 const char *p;
0424 char *tmp;
0425
0426 xbc_node_for_each_subkey(hnode, node) {
0427 p = xbc_node_get_data(node);
0428 if (!isdigit(p[0]))
0429 continue;
0430
0431 if (trace_boot_compose_hist_cmd(node, buf, size) == 0) {
0432 tmp = kstrdup(buf, GFP_KERNEL);
0433 if (!tmp)
0434 return;
0435 if (trigger_process_regex(file, buf) < 0)
0436 pr_err("Failed to apply hist trigger: %s\n", tmp);
0437 kfree(tmp);
0438 }
0439 }
0440
0441 if (xbc_node_find_subkey(hnode, "keys")) {
0442 if (trace_boot_compose_hist_cmd(hnode, buf, size) == 0) {
0443 tmp = kstrdup(buf, GFP_KERNEL);
0444 if (!tmp)
0445 return;
0446 if (trigger_process_regex(file, buf) < 0)
0447 pr_err("Failed to apply hist trigger: %s\n", tmp);
0448 kfree(tmp);
0449 }
0450 }
0451 }
0452 #else
0453 static void __init
0454 trace_boot_init_histograms(struct trace_event_file *file,
0455 struct xbc_node *hnode, char *buf, size_t size)
0456 {
0457
0458 }
0459 #endif
0460
0461 static void __init
0462 trace_boot_init_one_event(struct trace_array *tr, struct xbc_node *gnode,
0463 struct xbc_node *enode)
0464 {
0465 struct trace_event_file *file;
0466 struct xbc_node *anode;
0467 char buf[MAX_BUF_LEN];
0468 const char *p, *group, *event;
0469
0470 group = xbc_node_get_data(gnode);
0471 event = xbc_node_get_data(enode);
0472
0473 if (!strcmp(group, "kprobes"))
0474 if (trace_boot_add_kprobe_event(enode, event) < 0)
0475 return;
0476 if (!strcmp(group, "synthetic"))
0477 if (trace_boot_add_synth_event(enode, event) < 0)
0478 return;
0479
0480 mutex_lock(&event_mutex);
0481 file = find_event_file(tr, group, event);
0482 if (!file) {
0483 pr_err("Failed to find event: %s:%s\n", group, event);
0484 goto out;
0485 }
0486
0487 p = xbc_node_find_value(enode, "filter", NULL);
0488 if (p && *p != '\0') {
0489 if (strlcpy(buf, p, ARRAY_SIZE(buf)) >= ARRAY_SIZE(buf))
0490 pr_err("filter string is too long: %s\n", p);
0491 else if (apply_event_filter(file, buf) < 0)
0492 pr_err("Failed to apply filter: %s\n", buf);
0493 }
0494
0495 if (IS_ENABLED(CONFIG_HIST_TRIGGERS)) {
0496 xbc_node_for_each_array_value(enode, "actions", anode, p) {
0497 if (strlcpy(buf, p, ARRAY_SIZE(buf)) >= ARRAY_SIZE(buf))
0498 pr_err("action string is too long: %s\n", p);
0499 else if (trigger_process_regex(file, buf) < 0)
0500 pr_err("Failed to apply an action: %s\n", p);
0501 }
0502 anode = xbc_node_find_subkey(enode, "hist");
0503 if (anode)
0504 trace_boot_init_histograms(file, anode, buf, ARRAY_SIZE(buf));
0505 } else if (xbc_node_find_value(enode, "actions", NULL))
0506 pr_err("Failed to apply event actions because CONFIG_HIST_TRIGGERS is not set.\n");
0507
0508 if (xbc_node_find_value(enode, "enable", NULL)) {
0509 if (trace_event_enable_disable(file, 1, 0) < 0)
0510 pr_err("Failed to enable event node: %s:%s\n",
0511 group, event);
0512 }
0513 out:
0514 mutex_unlock(&event_mutex);
0515 }
0516
0517 static void __init
0518 trace_boot_init_events(struct trace_array *tr, struct xbc_node *node)
0519 {
0520 struct xbc_node *gnode, *enode;
0521 bool enable, enable_all = false;
0522 const char *data;
0523
0524 node = xbc_node_find_subkey(node, "event");
0525 if (!node)
0526 return;
0527
0528 xbc_node_for_each_subkey(node, gnode) {
0529 data = xbc_node_get_data(gnode);
0530 if (!strcmp(data, "enable")) {
0531 enable_all = true;
0532 continue;
0533 }
0534 enable = false;
0535 xbc_node_for_each_subkey(gnode, enode) {
0536 data = xbc_node_get_data(enode);
0537 if (!strcmp(data, "enable")) {
0538 enable = true;
0539 continue;
0540 }
0541 trace_boot_init_one_event(tr, gnode, enode);
0542 }
0543
0544 if (enable) {
0545 data = xbc_node_get_data(gnode);
0546 trace_array_set_clr_event(tr, data, NULL, true);
0547 }
0548 }
0549
0550 if (enable_all)
0551 trace_array_set_clr_event(tr, NULL, NULL, true);
0552 }
0553 #else
0554 #define trace_boot_enable_events(tr, node) do {} while (0)
0555 #define trace_boot_init_events(tr, node) do {} while (0)
0556 #endif
0557
0558 #ifdef CONFIG_DYNAMIC_FTRACE
0559 static void __init
0560 trace_boot_set_ftrace_filter(struct trace_array *tr, struct xbc_node *node)
0561 {
0562 struct xbc_node *anode;
0563 const char *p;
0564 char *q;
0565
0566 xbc_node_for_each_array_value(node, "ftrace.filters", anode, p) {
0567 q = kstrdup(p, GFP_KERNEL);
0568 if (!q)
0569 return;
0570 if (ftrace_set_filter(tr->ops, q, strlen(q), 0) < 0)
0571 pr_err("Failed to add %s to ftrace filter\n", p);
0572 else
0573 ftrace_filter_param = true;
0574 kfree(q);
0575 }
0576 xbc_node_for_each_array_value(node, "ftrace.notraces", anode, p) {
0577 q = kstrdup(p, GFP_KERNEL);
0578 if (!q)
0579 return;
0580 if (ftrace_set_notrace(tr->ops, q, strlen(q), 0) < 0)
0581 pr_err("Failed to add %s to ftrace filter\n", p);
0582 else
0583 ftrace_filter_param = true;
0584 kfree(q);
0585 }
0586 }
0587 #else
0588 #define trace_boot_set_ftrace_filter(tr, node) do {} while (0)
0589 #endif
0590
0591 static void __init
0592 trace_boot_enable_tracer(struct trace_array *tr, struct xbc_node *node)
0593 {
0594 const char *p;
0595
0596 trace_boot_set_ftrace_filter(tr, node);
0597
0598 p = xbc_node_find_value(node, "tracer", NULL);
0599 if (p && *p != '\0') {
0600 if (tracing_set_tracer(tr, p) < 0)
0601 pr_err("Failed to set given tracer: %s\n", p);
0602 }
0603
0604
0605 if (xbc_node_find_value(node, "alloc_snapshot", NULL)) {
0606 if (tracing_alloc_snapshot_instance(tr) < 0)
0607 pr_err("Failed to allocate snapshot buffer\n");
0608 }
0609 }
0610
0611 static void __init
0612 trace_boot_init_one_instance(struct trace_array *tr, struct xbc_node *node)
0613 {
0614 trace_boot_set_instance_options(tr, node);
0615 trace_boot_init_events(tr, node);
0616 trace_boot_enable_events(tr, node);
0617 trace_boot_enable_tracer(tr, node);
0618 }
0619
0620 static void __init
0621 trace_boot_init_instances(struct xbc_node *node)
0622 {
0623 struct xbc_node *inode;
0624 struct trace_array *tr;
0625 const char *p;
0626
0627 node = xbc_node_find_subkey(node, "instance");
0628 if (!node)
0629 return;
0630
0631 xbc_node_for_each_subkey(node, inode) {
0632 p = xbc_node_get_data(inode);
0633 if (!p || *p == '\0')
0634 continue;
0635
0636 tr = trace_array_get_by_name(p);
0637 if (!tr) {
0638 pr_err("Failed to get trace instance %s\n", p);
0639 continue;
0640 }
0641 trace_boot_init_one_instance(tr, inode);
0642 trace_array_put(tr);
0643 }
0644 }
0645
0646 static int __init trace_boot_init(void)
0647 {
0648 struct xbc_node *trace_node;
0649 struct trace_array *tr;
0650
0651 trace_node = xbc_find_node("ftrace");
0652 if (!trace_node)
0653 return 0;
0654
0655 tr = top_trace_array();
0656 if (!tr)
0657 return 0;
0658
0659
0660 trace_boot_init_one_instance(tr, trace_node);
0661 trace_boot_init_instances(trace_node);
0662
0663 disable_tracing_selftest("running boot-time tracing");
0664
0665 return 0;
0666 }
0667
0668
0669
0670
0671 core_initcall_sync(trace_boot_init);