Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

tracing/fprobe: Enable fprobe events with CONFIG_DYNAMIC_FTRACE_WITH_ARGS

Allow fprobe events to be enabled with CONFIG_DYNAMIC_FTRACE_WITH_ARGS.
With this change, fprobe events mostly use ftrace_regs instead of pt_regs.
Note that if the arch doesn't enable HAVE_FTRACE_REGS_HAVING_PT_REGS,
fprobe events will not be able to be used from perf.

Cc: Alexei Starovoitov <alexei.starovoitov@gmail.com>
Cc: Florent Revest <revest@chromium.org>
Cc: Martin KaFai Lau <martin.lau@linux.dev>
Cc: bpf <bpf@vger.kernel.org>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Alan Maguire <alan.maguire@oracle.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Link: https://lore.kernel.org/173518999352.391279.13332699755290175168.stgit@devnote2
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>

authored by

Masami Hiramatsu (Google) and committed by
Steven Rostedt (Google)
0566cefe d5d01b71

+86 -42
+17
include/linux/ftrace.h
··· 250 250 return ftrace_get_regs(fregs) != NULL; 251 251 } 252 252 253 + #ifdef CONFIG_HAVE_REGS_AND_STACK_ACCESS_API 254 + static __always_inline unsigned long 255 + ftrace_regs_get_kernel_stack_nth(struct ftrace_regs *fregs, unsigned int nth) 256 + { 257 + unsigned long *stackp; 258 + 259 + stackp = (unsigned long *)ftrace_regs_get_stack_pointer(fregs); 260 + if (((unsigned long)(stackp + nth) & ~(THREAD_SIZE - 1)) == 261 + ((unsigned long)stackp & ~(THREAD_SIZE - 1))) 262 + return *(stackp + nth); 263 + 264 + return 0; 265 + } 266 + #else /* !CONFIG_HAVE_REGS_AND_STACK_ACCESS_API */ 267 + #define ftrace_regs_get_kernel_stack_nth(fregs, nth) (0L) 268 + #endif /* CONFIG_HAVE_REGS_AND_STACK_ACCESS_API */ 269 + 253 270 typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip, 254 271 struct ftrace_ops *op, struct ftrace_regs *fregs); 255 272
-1
kernel/trace/Kconfig
··· 689 689 select TRACING 690 690 select PROBE_EVENTS 691 691 select DYNAMIC_EVENTS 692 - depends on DYNAMIC_FTRACE_WITH_REGS 693 692 default y 694 693 help 695 694 This allows user to add tracing events on the function entry and
+68 -40
kernel/trace/trace_fprobe.c
··· 134 134 process_fetch_insn(struct fetch_insn *code, void *rec, void *edata, 135 135 void *dest, void *base) 136 136 { 137 - struct pt_regs *regs = rec; 137 + struct ftrace_regs *fregs = rec; 138 138 unsigned long val; 139 139 int ret; 140 140 ··· 142 142 /* 1st stage: get value from context */ 143 143 switch (code->op) { 144 144 case FETCH_OP_STACK: 145 - val = regs_get_kernel_stack_nth(regs, code->param); 145 + val = ftrace_regs_get_kernel_stack_nth(fregs, code->param); 146 146 break; 147 147 case FETCH_OP_STACKP: 148 - val = kernel_stack_pointer(regs); 148 + val = ftrace_regs_get_stack_pointer(fregs); 149 149 break; 150 150 case FETCH_OP_RETVAL: 151 - val = regs_return_value(regs); 151 + val = ftrace_regs_get_return_value(fregs); 152 152 break; 153 153 #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API 154 154 case FETCH_OP_ARG: 155 - val = regs_get_kernel_argument(regs, code->param); 155 + val = ftrace_regs_get_argument(fregs, code->param); 156 156 break; 157 157 case FETCH_OP_EDATA: 158 158 val = *(unsigned long *)((unsigned long)edata + code->offset); ··· 175 175 /* function entry handler */ 176 176 static nokprobe_inline void 177 177 __fentry_trace_func(struct trace_fprobe *tf, unsigned long entry_ip, 178 - struct pt_regs *regs, 178 + struct ftrace_regs *fregs, 179 179 struct trace_event_file *trace_file) 180 180 { 181 181 struct fentry_trace_entry_head *entry; ··· 189 189 if (trace_trigger_soft_disabled(trace_file)) 190 190 return; 191 191 192 - dsize = __get_data_size(&tf->tp, regs, NULL); 192 + dsize = __get_data_size(&tf->tp, fregs, NULL); 193 193 194 194 entry = trace_event_buffer_reserve(&fbuffer, trace_file, 195 195 sizeof(*entry) + tf->tp.size + dsize); 196 196 if (!entry) 197 197 return; 198 198 199 - fbuffer.regs = regs; 199 + fbuffer.regs = ftrace_get_regs(fregs); 200 200 entry = fbuffer.entry = ring_buffer_event_data(fbuffer.event); 201 201 entry->ip = entry_ip; 202 - store_trace_args(&entry[1], &tf->tp, regs, NULL, sizeof(*entry), dsize); 202 + store_trace_args(&entry[1], &tf->tp, fregs, NULL, sizeof(*entry), dsize); 203 203 204 204 trace_event_buffer_commit(&fbuffer); 205 205 } 206 206 207 207 static void 208 208 fentry_trace_func(struct trace_fprobe *tf, unsigned long entry_ip, 209 - struct pt_regs *regs) 209 + struct ftrace_regs *fregs) 210 210 { 211 211 struct event_file_link *link; 212 212 213 213 trace_probe_for_each_link_rcu(link, &tf->tp) 214 - __fentry_trace_func(tf, entry_ip, regs, link->file); 214 + __fentry_trace_func(tf, entry_ip, fregs, link->file); 215 215 } 216 216 NOKPROBE_SYMBOL(fentry_trace_func); 217 + 218 + static nokprobe_inline 219 + void store_fprobe_entry_data(void *edata, struct trace_probe *tp, struct ftrace_regs *fregs) 220 + { 221 + struct probe_entry_arg *earg = tp->entry_arg; 222 + unsigned long val = 0; 223 + int i; 224 + 225 + if (!earg) 226 + return; 227 + 228 + for (i = 0; i < earg->size; i++) { 229 + struct fetch_insn *code = &earg->code[i]; 230 + 231 + switch (code->op) { 232 + case FETCH_OP_ARG: 233 + val = ftrace_regs_get_argument(fregs, code->param); 234 + break; 235 + case FETCH_OP_ST_EDATA: 236 + *(unsigned long *)((unsigned long)edata + code->offset) = val; 237 + break; 238 + case FETCH_OP_END: 239 + goto end; 240 + default: 241 + break; 242 + } 243 + } 244 + end: 245 + return; 246 + } 217 247 218 248 /* function exit handler */ 219 249 static int trace_fprobe_entry_handler(struct fprobe *fp, unsigned long entry_ip, ··· 251 221 void *entry_data) 252 222 { 253 223 struct trace_fprobe *tf = container_of(fp, struct trace_fprobe, fp); 254 - struct pt_regs *regs = ftrace_get_regs(fregs); 255 224 256 - if (regs && tf->tp.entry_arg) 257 - store_trace_entry_data(entry_data, &tf->tp, regs); 225 + if (tf->tp.entry_arg) 226 + store_fprobe_entry_data(entry_data, &tf->tp, fregs); 258 227 259 228 return 0; 260 229 } ··· 261 232 262 233 static nokprobe_inline void 263 234 __fexit_trace_func(struct trace_fprobe *tf, unsigned long entry_ip, 264 - unsigned long ret_ip, struct pt_regs *regs, 235 + unsigned long ret_ip, struct ftrace_regs *fregs, 265 236 void *entry_data, struct trace_event_file *trace_file) 266 237 { 267 238 struct fexit_trace_entry_head *entry; ··· 275 246 if (trace_trigger_soft_disabled(trace_file)) 276 247 return; 277 248 278 - dsize = __get_data_size(&tf->tp, regs, entry_data); 249 + dsize = __get_data_size(&tf->tp, fregs, entry_data); 279 250 280 251 entry = trace_event_buffer_reserve(&fbuffer, trace_file, 281 252 sizeof(*entry) + tf->tp.size + dsize); 282 253 if (!entry) 283 254 return; 284 255 285 - fbuffer.regs = regs; 256 + fbuffer.regs = ftrace_get_regs(fregs); 286 257 entry = fbuffer.entry = ring_buffer_event_data(fbuffer.event); 287 258 entry->func = entry_ip; 288 259 entry->ret_ip = ret_ip; 289 - store_trace_args(&entry[1], &tf->tp, regs, entry_data, sizeof(*entry), dsize); 260 + store_trace_args(&entry[1], &tf->tp, fregs, entry_data, sizeof(*entry), dsize); 290 261 291 262 trace_event_buffer_commit(&fbuffer); 292 263 } 293 264 294 265 static void 295 266 fexit_trace_func(struct trace_fprobe *tf, unsigned long entry_ip, 296 - unsigned long ret_ip, struct pt_regs *regs, void *entry_data) 267 + unsigned long ret_ip, struct ftrace_regs *fregs, void *entry_data) 297 268 { 298 269 struct event_file_link *link; 299 270 300 271 trace_probe_for_each_link_rcu(link, &tf->tp) 301 - __fexit_trace_func(tf, entry_ip, ret_ip, regs, entry_data, link->file); 272 + __fexit_trace_func(tf, entry_ip, ret_ip, fregs, entry_data, link->file); 302 273 } 303 274 NOKPROBE_SYMBOL(fexit_trace_func); 304 275 305 276 #ifdef CONFIG_PERF_EVENTS 306 277 307 278 static int fentry_perf_func(struct trace_fprobe *tf, unsigned long entry_ip, 308 - struct pt_regs *regs) 279 + struct ftrace_regs *fregs) 309 280 { 310 281 struct trace_event_call *call = trace_probe_event_call(&tf->tp); 311 282 struct fentry_trace_entry_head *entry; 312 283 struct hlist_head *head; 313 284 int size, __size, dsize; 285 + struct pt_regs *regs; 314 286 int rctx; 315 287 316 288 head = this_cpu_ptr(call->perf_events); 317 289 if (hlist_empty(head)) 318 290 return 0; 319 291 320 - dsize = __get_data_size(&tf->tp, regs, NULL); 292 + dsize = __get_data_size(&tf->tp, fregs, NULL); 321 293 __size = sizeof(*entry) + tf->tp.size + dsize; 322 294 size = ALIGN(__size + sizeof(u32), sizeof(u64)); 323 295 size -= sizeof(u32); 324 296 325 - entry = perf_trace_buf_alloc(size, NULL, &rctx); 297 + entry = perf_trace_buf_alloc(size, &regs, &rctx); 326 298 if (!entry) 327 299 return 0; 328 300 301 + regs = ftrace_fill_perf_regs(fregs, regs); 302 + 329 303 entry->ip = entry_ip; 330 304 memset(&entry[1], 0, dsize); 331 - store_trace_args(&entry[1], &tf->tp, regs, NULL, sizeof(*entry), dsize); 305 + store_trace_args(&entry[1], &tf->tp, fregs, NULL, sizeof(*entry), dsize); 332 306 perf_trace_buf_submit(entry, size, rctx, call->event.type, 1, regs, 333 307 head, NULL); 334 308 return 0; ··· 340 308 341 309 static void 342 310 fexit_perf_func(struct trace_fprobe *tf, unsigned long entry_ip, 343 - unsigned long ret_ip, struct pt_regs *regs, 311 + unsigned long ret_ip, struct ftrace_regs *fregs, 344 312 void *entry_data) 345 313 { 346 314 struct trace_event_call *call = trace_probe_event_call(&tf->tp); 347 315 struct fexit_trace_entry_head *entry; 348 316 struct hlist_head *head; 349 317 int size, __size, dsize; 318 + struct pt_regs *regs; 350 319 int rctx; 351 320 352 321 head = this_cpu_ptr(call->perf_events); 353 322 if (hlist_empty(head)) 354 323 return; 355 324 356 - dsize = __get_data_size(&tf->tp, regs, entry_data); 325 + dsize = __get_data_size(&tf->tp, fregs, entry_data); 357 326 __size = sizeof(*entry) + tf->tp.size + dsize; 358 327 size = ALIGN(__size + sizeof(u32), sizeof(u64)); 359 328 size -= sizeof(u32); 360 329 361 - entry = perf_trace_buf_alloc(size, NULL, &rctx); 330 + entry = perf_trace_buf_alloc(size, &regs, &rctx); 362 331 if (!entry) 363 332 return; 364 333 334 + regs = ftrace_fill_perf_regs(fregs, regs); 335 + 365 336 entry->func = entry_ip; 366 337 entry->ret_ip = ret_ip; 367 - store_trace_args(&entry[1], &tf->tp, regs, entry_data, sizeof(*entry), dsize); 338 + store_trace_args(&entry[1], &tf->tp, fregs, entry_data, sizeof(*entry), dsize); 368 339 perf_trace_buf_submit(entry, size, rctx, call->event.type, 1, regs, 369 340 head, NULL); 370 341 } ··· 379 344 void *entry_data) 380 345 { 381 346 struct trace_fprobe *tf = container_of(fp, struct trace_fprobe, fp); 382 - struct pt_regs *regs = ftrace_get_regs(fregs); 383 347 int ret = 0; 384 348 385 - if (!regs) 386 - return 0; 387 - 388 349 if (trace_probe_test_flag(&tf->tp, TP_FLAG_TRACE)) 389 - fentry_trace_func(tf, entry_ip, regs); 350 + fentry_trace_func(tf, entry_ip, fregs); 351 + 390 352 #ifdef CONFIG_PERF_EVENTS 391 353 if (trace_probe_test_flag(&tf->tp, TP_FLAG_PROFILE)) 392 - ret = fentry_perf_func(tf, entry_ip, regs); 354 + ret = fentry_perf_func(tf, entry_ip, fregs); 393 355 #endif 394 356 return ret; 395 357 } ··· 397 365 void *entry_data) 398 366 { 399 367 struct trace_fprobe *tf = container_of(fp, struct trace_fprobe, fp); 400 - struct pt_regs *regs = ftrace_get_regs(fregs); 401 - 402 - if (!regs) 403 - return; 404 368 405 369 if (trace_probe_test_flag(&tf->tp, TP_FLAG_TRACE)) 406 - fexit_trace_func(tf, entry_ip, ret_ip, regs, entry_data); 370 + fexit_trace_func(tf, entry_ip, ret_ip, fregs, entry_data); 407 371 #ifdef CONFIG_PERF_EVENTS 408 372 if (trace_probe_test_flag(&tf->tp, TP_FLAG_PROFILE)) 409 - fexit_perf_func(tf, entry_ip, ret_ip, regs, entry_data); 373 + fexit_perf_func(tf, entry_ip, ret_ip, fregs, entry_data); 410 374 #endif 411 375 } 412 376 NOKPROBE_SYMBOL(fexit_dispatcher);
+1 -1
kernel/trace/trace_probe_tmpl.h
··· 232 232 233 233 /* Sum up total data length for dynamic arrays (strings) */ 234 234 static nokprobe_inline int 235 - __get_data_size(struct trace_probe *tp, struct pt_regs *regs, void *edata) 235 + __get_data_size(struct trace_probe *tp, void *regs, void *edata) 236 236 { 237 237 struct probe_arg *arg; 238 238 int i, len, ret = 0;