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 static int __init 92 trace_boot_add_kprobe_event(struct xbc_node *node, const char *event) 93 { 94 struct dynevent_cmd cmd; 95 struct xbc_node *anode; 96 char buf[MAX_BUF_LEN]; 97 const char *val; 98 int ret; 99 100 kprobe_event_cmd_init(&cmd, buf, MAX_BUF_LEN); 101 102 ret = kprobe_event_gen_cmd_start(&cmd, event, NULL); 103 if (ret) 104 return ret; 105 106 xbc_node_for_each_array_value(node, "probes", anode, val) { 107 ret = kprobe_event_add_field(&cmd, val); 108 if (ret) 109 return ret; 110 } 111 112 ret = kprobe_event_gen_cmd_end(&cmd); 113 if (ret) 114 pr_err("Failed to add probe: %s\n", buf); 115 116 return ret; 117 } 118 #else 119 static inline int __init 120 trace_boot_add_kprobe_event(struct xbc_node *node, const char *event) 121 { 122 pr_err("Kprobe event is not supported.\n"); 123 return -ENOTSUPP; 124 } 125 #endif 126 127 #ifdef CONFIG_HIST_TRIGGERS 128 extern int synth_event_run_command(const char *command); 129 130 static int __init 131 trace_boot_add_synth_event(struct xbc_node *node, const char *event) 132 { 133 struct xbc_node *anode; 134 char buf[MAX_BUF_LEN], *q; 135 const char *p; 136 int len, delta, ret; 137 138 len = ARRAY_SIZE(buf); 139 delta = snprintf(buf, len, "%s", event); 140 if (delta >= len) { 141 pr_err("Event name is too long: %s\n", event); 142 return -E2BIG; 143 } 144 len -= delta; q = buf + delta; 145 146 xbc_node_for_each_array_value(node, "fields", anode, p) { 147 delta = snprintf(q, len, " %s;", p); 148 if (delta >= len) { 149 pr_err("fields string is too long: %s\n", p); 150 return -E2BIG; 151 } 152 len -= delta; q += delta; 153 } 154 155 ret = synth_event_run_command(buf); 156 if (ret < 0) 157 pr_err("Failed to add synthetic event: %s\n", buf); 158 159 160 return ret; 161 } 162 #else 163 static inline int __init 164 trace_boot_add_synth_event(struct xbc_node *node, const char *event) 165 { 166 pr_err("Synthetic event is not supported.\n"); 167 return -ENOTSUPP; 168 } 169 #endif 170 171 static void __init 172 trace_boot_init_one_event(struct trace_array *tr, struct xbc_node *gnode, 173 struct xbc_node *enode) 174 { 175 struct trace_event_file *file; 176 struct xbc_node *anode; 177 char buf[MAX_BUF_LEN]; 178 const char *p, *group, *event; 179 180 group = xbc_node_get_data(gnode); 181 event = xbc_node_get_data(enode); 182 183 if (!strcmp(group, "kprobes")) 184 if (trace_boot_add_kprobe_event(enode, event) < 0) 185 return; 186 if (!strcmp(group, "synthetic")) 187 if (trace_boot_add_synth_event(enode, event) < 0) 188 return; 189 190 mutex_lock(&event_mutex); 191 file = find_event_file(tr, group, event); 192 if (!file) { 193 pr_err("Failed to find event: %s:%s\n", group, event); 194 goto out; 195 } 196 197 p = xbc_node_find_value(enode, "filter", NULL); 198 if (p && *p != '\0') { 199 if (strlcpy(buf, p, ARRAY_SIZE(buf)) >= ARRAY_SIZE(buf)) 200 pr_err("filter string is too long: %s\n", p); 201 else if (apply_event_filter(file, buf) < 0) 202 pr_err("Failed to apply filter: %s\n", buf); 203 } 204 205 xbc_node_for_each_array_value(enode, "actions", anode, p) { 206 if (strlcpy(buf, p, ARRAY_SIZE(buf)) >= ARRAY_SIZE(buf)) 207 pr_err("action string is too long: %s\n", p); 208 else if (trigger_process_regex(file, buf) < 0) 209 pr_err("Failed to apply an action: %s\n", buf); 210 } 211 212 if (xbc_node_find_value(enode, "enable", NULL)) { 213 if (trace_event_enable_disable(file, 1, 0) < 0) 214 pr_err("Failed to enable event node: %s:%s\n", 215 group, event); 216 } 217 out: 218 mutex_unlock(&event_mutex); 219 } 220 221 static void __init 222 trace_boot_init_events(struct trace_array *tr, struct xbc_node *node) 223 { 224 struct xbc_node *gnode, *enode; 225 226 node = xbc_node_find_child(node, "event"); 227 if (!node) 228 return; 229 /* per-event key starts with "event.GROUP.EVENT" */ 230 xbc_node_for_each_child(node, gnode) 231 xbc_node_for_each_child(gnode, enode) 232 trace_boot_init_one_event(tr, gnode, enode); 233 } 234 #else 235 #define trace_boot_enable_events(tr, node) do {} while (0) 236 #define trace_boot_init_events(tr, node) do {} while (0) 237 #endif 238 239 #ifdef CONFIG_DYNAMIC_FTRACE 240 static void __init 241 trace_boot_set_ftrace_filter(struct trace_array *tr, struct xbc_node *node) 242 { 243 struct xbc_node *anode; 244 const char *p; 245 char *q; 246 247 xbc_node_for_each_array_value(node, "ftrace.filters", anode, p) { 248 q = kstrdup(p, GFP_KERNEL); 249 if (!q) 250 return; 251 if (ftrace_set_filter(tr->ops, q, strlen(q), 0) < 0) 252 pr_err("Failed to add %s to ftrace filter\n", p); 253 else 254 ftrace_filter_param = true; 255 kfree(q); 256 } 257 xbc_node_for_each_array_value(node, "ftrace.notraces", anode, p) { 258 q = kstrdup(p, GFP_KERNEL); 259 if (!q) 260 return; 261 if (ftrace_set_notrace(tr->ops, q, strlen(q), 0) < 0) 262 pr_err("Failed to add %s to ftrace filter\n", p); 263 else 264 ftrace_filter_param = true; 265 kfree(q); 266 } 267 } 268 #else 269 #define trace_boot_set_ftrace_filter(tr, node) do {} while (0) 270 #endif 271 272 static void __init 273 trace_boot_enable_tracer(struct trace_array *tr, struct xbc_node *node) 274 { 275 const char *p; 276 277 trace_boot_set_ftrace_filter(tr, node); 278 279 p = xbc_node_find_value(node, "tracer", NULL); 280 if (p && *p != '\0') { 281 if (tracing_set_tracer(tr, p) < 0) 282 pr_err("Failed to set given tracer: %s\n", p); 283 } 284 } 285 286 static void __init 287 trace_boot_init_one_instance(struct trace_array *tr, struct xbc_node *node) 288 { 289 trace_boot_set_instance_options(tr, node); 290 trace_boot_init_events(tr, node); 291 trace_boot_enable_events(tr, node); 292 trace_boot_enable_tracer(tr, node); 293 } 294 295 static void __init 296 trace_boot_init_instances(struct xbc_node *node) 297 { 298 struct xbc_node *inode; 299 struct trace_array *tr; 300 const char *p; 301 302 node = xbc_node_find_child(node, "instance"); 303 if (!node) 304 return; 305 306 xbc_node_for_each_child(node, inode) { 307 p = xbc_node_get_data(inode); 308 if (!p || *p == '\0') 309 continue; 310 311 tr = trace_array_get_by_name(p); 312 if (!tr) { 313 pr_err("Failed to get trace instance %s\n", p); 314 continue; 315 } 316 trace_boot_init_one_instance(tr, inode); 317 trace_array_put(tr); 318 } 319 } 320 321 static int __init trace_boot_init(void) 322 { 323 struct xbc_node *trace_node; 324 struct trace_array *tr; 325 326 trace_node = xbc_find_node("ftrace"); 327 if (!trace_node) 328 return 0; 329 330 tr = top_trace_array(); 331 if (!tr) 332 return 0; 333 334 /* Global trace array is also one instance */ 335 trace_boot_init_one_instance(tr, trace_node); 336 trace_boot_init_instances(trace_node); 337 338 return 0; 339 } 340 341 fs_initcall(trace_boot_init); 342