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 22 #define MAX_BUF_LEN 256 23 24 static void __init 25 trace_boot_set_instance_options(struct trace_array *tr, struct xbc_node *node) 26 { 27 struct xbc_node *anode; 28 const char *p; 29 char buf[MAX_BUF_LEN]; 30 unsigned long v = 0; 31 32 /* Common ftrace options */ 33 xbc_node_for_each_array_value(node, "options", anode, p) { 34 if (strlcpy(buf, p, ARRAY_SIZE(buf)) >= ARRAY_SIZE(buf)) { 35 pr_err("String is too long: %s\n", p); 36 continue; 37 } 38 39 if (trace_set_options(tr, buf) < 0) 40 pr_err("Failed to set option: %s\n", buf); 41 } 42 43 p = xbc_node_find_value(node, "trace_clock", NULL); 44 if (p && *p != '\0') { 45 if (tracing_set_clock(tr, p) < 0) 46 pr_err("Failed to set trace clock: %s\n", p); 47 } 48 49 p = xbc_node_find_value(node, "buffer_size", NULL); 50 if (p && *p != '\0') { 51 v = memparse(p, NULL); 52 if (v < PAGE_SIZE) 53 pr_err("Buffer size is too small: %s\n", p); 54 if (tracing_resize_ring_buffer(tr, v, RING_BUFFER_ALL_CPUS) < 0) 55 pr_err("Failed to resize trace buffer to %s\n", p); 56 } 57 58 p = xbc_node_find_value(node, "cpumask", NULL); 59 if (p && *p != '\0') { 60 cpumask_var_t new_mask; 61 62 if (alloc_cpumask_var(&new_mask, GFP_KERNEL)) { 63 if (cpumask_parse(p, new_mask) < 0 || 64 tracing_set_cpumask(tr, new_mask) < 0) 65 pr_err("Failed to set new CPU mask %s\n", p); 66 free_cpumask_var(new_mask); 67 } 68 } 69 } 70 71 #ifdef CONFIG_EVENT_TRACING 72 static void __init 73 trace_boot_enable_events(struct trace_array *tr, struct xbc_node *node) 74 { 75 struct xbc_node *anode; 76 char buf[MAX_BUF_LEN]; 77 const char *p; 78 79 xbc_node_for_each_array_value(node, "events", anode, p) { 80 if (strlcpy(buf, p, ARRAY_SIZE(buf)) >= ARRAY_SIZE(buf)) { 81 pr_err("String is too long: %s\n", p); 82 continue; 83 } 84 85 if (ftrace_set_clr_event(tr, buf, 1) < 0) 86 pr_err("Failed to enable event: %s\n", p); 87 } 88 } 89 90 #ifdef CONFIG_KPROBE_EVENTS 91 extern int trace_kprobe_run_command(const char *command); 92 93 static int __init 94 trace_boot_add_kprobe_event(struct xbc_node *node, const char *event) 95 { 96 struct xbc_node *anode; 97 char buf[MAX_BUF_LEN]; 98 const char *val; 99 char *p; 100 int len; 101 102 len = snprintf(buf, ARRAY_SIZE(buf) - 1, "p:kprobes/%s ", event); 103 if (len >= ARRAY_SIZE(buf)) { 104 pr_err("Event name is too long: %s\n", event); 105 return -E2BIG; 106 } 107 p = buf + len; 108 len = ARRAY_SIZE(buf) - len; 109 110 xbc_node_for_each_array_value(node, "probes", anode, val) { 111 if (strlcpy(p, val, len) >= len) { 112 pr_err("Probe definition is too long: %s\n", val); 113 return -E2BIG; 114 } 115 if (trace_kprobe_run_command(buf) < 0) { 116 pr_err("Failed to add probe: %s\n", buf); 117 return -EINVAL; 118 } 119 } 120 121 return 0; 122 } 123 #else 124 static inline int __init 125 trace_boot_add_kprobe_event(struct xbc_node *node, const char *event) 126 { 127 pr_err("Kprobe event is not supported.\n"); 128 return -ENOTSUPP; 129 } 130 #endif 131 132 #ifdef CONFIG_HIST_TRIGGERS 133 extern int synth_event_run_command(const char *command); 134 135 static int __init 136 trace_boot_add_synth_event(struct xbc_node *node, const char *event) 137 { 138 struct xbc_node *anode; 139 char buf[MAX_BUF_LEN], *q; 140 const char *p; 141 int len, delta, ret; 142 143 len = ARRAY_SIZE(buf); 144 delta = snprintf(buf, len, "%s", event); 145 if (delta >= len) { 146 pr_err("Event name is too long: %s\n", event); 147 return -E2BIG; 148 } 149 len -= delta; q = buf + delta; 150 151 xbc_node_for_each_array_value(node, "fields", anode, p) { 152 delta = snprintf(q, len, " %s;", p); 153 if (delta >= len) { 154 pr_err("fields string is too long: %s\n", p); 155 return -E2BIG; 156 } 157 len -= delta; q += delta; 158 } 159 160 ret = synth_event_run_command(buf); 161 if (ret < 0) 162 pr_err("Failed to add synthetic event: %s\n", buf); 163 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 static void __init 177 trace_boot_init_one_event(struct trace_array *tr, struct xbc_node *gnode, 178 struct xbc_node *enode) 179 { 180 struct trace_event_file *file; 181 struct xbc_node *anode; 182 char buf[MAX_BUF_LEN]; 183 const char *p, *group, *event; 184 185 group = xbc_node_get_data(gnode); 186 event = xbc_node_get_data(enode); 187 188 if (!strcmp(group, "kprobes")) 189 if (trace_boot_add_kprobe_event(enode, event) < 0) 190 return; 191 if (!strcmp(group, "synthetic")) 192 if (trace_boot_add_synth_event(enode, event) < 0) 193 return; 194 195 mutex_lock(&event_mutex); 196 file = find_event_file(tr, group, event); 197 if (!file) { 198 pr_err("Failed to find event: %s:%s\n", group, event); 199 goto out; 200 } 201 202 p = xbc_node_find_value(enode, "filter", NULL); 203 if (p && *p != '\0') { 204 if (strlcpy(buf, p, ARRAY_SIZE(buf)) >= ARRAY_SIZE(buf)) 205 pr_err("filter string is too long: %s\n", p); 206 else if (apply_event_filter(file, buf) < 0) 207 pr_err("Failed to apply filter: %s\n", buf); 208 } 209 210 xbc_node_for_each_array_value(enode, "actions", anode, p) { 211 if (strlcpy(buf, p, ARRAY_SIZE(buf)) >= ARRAY_SIZE(buf)) 212 pr_err("action string is too long: %s\n", p); 213 else if (trigger_process_regex(file, buf) < 0) 214 pr_err("Failed to apply an action: %s\n", buf); 215 } 216 217 if (xbc_node_find_value(enode, "enable", NULL)) { 218 if (trace_event_enable_disable(file, 1, 0) < 0) 219 pr_err("Failed to enable event node: %s:%s\n", 220 group, event); 221 } 222 out: 223 mutex_unlock(&event_mutex); 224 } 225 226 static void __init 227 trace_boot_init_events(struct trace_array *tr, struct xbc_node *node) 228 { 229 struct xbc_node *gnode, *enode; 230 231 node = xbc_node_find_child(node, "event"); 232 if (!node) 233 return; 234 /* per-event key starts with "event.GROUP.EVENT" */ 235 xbc_node_for_each_child(node, gnode) 236 xbc_node_for_each_child(gnode, enode) 237 trace_boot_init_one_event(tr, gnode, enode); 238 } 239 #else 240 #define trace_boot_enable_events(tr, node) do {} while (0) 241 #define trace_boot_init_events(tr, node) do {} while (0) 242 #endif 243 244 #ifdef CONFIG_DYNAMIC_FTRACE 245 static void __init 246 trace_boot_set_ftrace_filter(struct trace_array *tr, struct xbc_node *node) 247 { 248 struct xbc_node *anode; 249 const char *p; 250 char *q; 251 252 xbc_node_for_each_array_value(node, "ftrace.filters", anode, p) { 253 q = kstrdup(p, GFP_KERNEL); 254 if (!q) 255 return; 256 if (ftrace_set_filter(tr->ops, q, strlen(q), 0) < 0) 257 pr_err("Failed to add %s to ftrace filter\n", p); 258 else 259 ftrace_filter_param = true; 260 kfree(q); 261 } 262 xbc_node_for_each_array_value(node, "ftrace.notraces", anode, p) { 263 q = kstrdup(p, GFP_KERNEL); 264 if (!q) 265 return; 266 if (ftrace_set_notrace(tr->ops, q, strlen(q), 0) < 0) 267 pr_err("Failed to add %s to ftrace filter\n", p); 268 else 269 ftrace_filter_param = true; 270 kfree(q); 271 } 272 } 273 #else 274 #define trace_boot_set_ftrace_filter(tr, node) do {} while (0) 275 #endif 276 277 static void __init 278 trace_boot_enable_tracer(struct trace_array *tr, struct xbc_node *node) 279 { 280 const char *p; 281 282 trace_boot_set_ftrace_filter(tr, node); 283 284 p = xbc_node_find_value(node, "tracer", NULL); 285 if (p && *p != '\0') { 286 if (tracing_set_tracer(tr, p) < 0) 287 pr_err("Failed to set given tracer: %s\n", p); 288 } 289 } 290 291 static void __init 292 trace_boot_init_one_instance(struct trace_array *tr, struct xbc_node *node) 293 { 294 trace_boot_set_instance_options(tr, node); 295 trace_boot_init_events(tr, node); 296 trace_boot_enable_events(tr, node); 297 trace_boot_enable_tracer(tr, node); 298 } 299 300 static void __init 301 trace_boot_init_instances(struct xbc_node *node) 302 { 303 struct xbc_node *inode; 304 struct trace_array *tr; 305 const char *p; 306 307 node = xbc_node_find_child(node, "instance"); 308 if (!node) 309 return; 310 311 xbc_node_for_each_child(node, inode) { 312 p = xbc_node_get_data(inode); 313 if (!p || *p == '\0') 314 continue; 315 316 tr = trace_array_get_by_name(p); 317 if (!tr) { 318 pr_err("Failed to get trace instance %s\n", p); 319 continue; 320 } 321 trace_boot_init_one_instance(tr, inode); 322 trace_array_put(tr); 323 } 324 } 325 326 static int __init trace_boot_init(void) 327 { 328 struct xbc_node *trace_node; 329 struct trace_array *tr; 330 331 trace_node = xbc_find_node("ftrace"); 332 if (!trace_node) 333 return 0; 334 335 tr = top_trace_array(); 336 if (!tr) 337 return 0; 338 339 /* Global trace array is also one instance */ 340 trace_boot_init_one_instance(tr, trace_node); 341 trace_boot_init_instances(trace_node); 342 343 return 0; 344 } 345 346 fs_initcall(trace_boot_init); 347