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 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 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 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 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 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 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 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 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 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 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 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 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 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) 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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