Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * trace_boot.c
0004  * Tracing kernel boot-time
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     /* Common ftrace options */
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     /* Compose 'handler' parameter */
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     /* Compose 'action' parameter */
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         /* All digit started node should be instances. */
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  * Histogram boottime tracing syntax.
0325  *
0326  * ftrace.[instance.INSTANCE.]event.GROUP.EVENT.hist[.N] {
0327  *  keys = <KEY>[,...]
0328  *  values = <VAL>[,...]
0329  *  sort = <SORT-KEY>[,...]
0330  *  size = <ENTRIES>
0331  *  name = <HISTNAME>
0332  *  var { <VAR> = <EXPR> ... }
0333  *  pause|continue|clear
0334  *  onmax|onchange[.N] { var = <VAR>; <ACTION> [= <PARAM>] }
0335  *  onmatch[.N] { event = <EVENT>; <ACTION> [= <PARAM>] }
0336  *  filter = <FILTER>
0337  * }
0338  *
0339  * Where <ACTION> are;
0340  *
0341  *  trace = <EVENT>, <ARG1>[, ...]
0342  *  save = <ARG1>[, ...]
0343  *  snapshot
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             /* Expression must not include spaces. */
0381             append_printf(&buf, end, ":%s=",
0382                       xbc_node_get_data(knode));
0383             append_str_nospace(&buf, end, p);
0384         }
0385     }
0386 
0387     /* Histogram control attributes (mutual exclusive) */
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     /* Histogram handler and actions */
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         /* All digit started node should be instances. */
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     /* do nothing */
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     /* per-event key starts with "event.GROUP.EVENT" */
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         /* Event enablement must be done after event settings */
0544         if (enable) {
0545             data = xbc_node_get_data(gnode);
0546             trace_array_set_clr_event(tr, data, NULL, true);
0547         }
0548     }
0549     /* Ditto */
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     /* Since tracer can free snapshot buffer, allocate snapshot here.*/
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     /* Global trace array is also one instance */
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  * Start tracing at the end of core-initcall, so that it starts tracing
0669  * from the beginning of postcore_initcall.
0670  */
0671 core_initcall_sync(trace_boot_init);