In preparation to have arguments of a function passed to callbacks attached to functions as default, change the default callback prototype to receive a struct ftrace_regs as the forth parameter instead of a pt_regs. For callbacks that set the FL_SAVE_REGS flag in their ftrace_ops flags, they will now need to get the pt_regs via a ftrace_get_regs() helper call. If this is called by a callback that their ftrace_ops did not have a FL_SAVE_REGS flag set, it that helper function will return NULL. This will allow the ftrace_regs to hold enough just to get the parameters and stack pointer, but without the worry that callbacks may have a pt_regs that is not completely filled.
Showing the changes to kernel (9 of 18 files). Show all
Unified · Split
| @@ -40,8 +40,9 @@ struct klp_ops *klp_find_ops(void *old_func) · 39 unmodified lines | ||
| 40 | 40 | static void notrace klp_ftrace_handler(unsigned long ip, |
| 41 | 41 | unsigned long parent_ip, |
| 42 | 42 | struct ftrace_ops *fops, |
| 43 | − struct pt_regs *regs) | |
| 43 | + struct ftrace_regs *fregs) | |
| 44 | 44 | { |
| 45 | + struct pt_regs *regs = ftrace_get_regs(fregs); | |
| 45 | 46 | struct klp_ops *ops; |
| 46 | 47 | struct klp_func *func; |
| 47 | 48 | int patch_state; |
| @@ -121,7 +121,7 @@ struct ftrace_ops global_ops; · 120 unmodified lines | ||
| 121 | 121 | |
| 122 | 122 | #if ARCH_SUPPORTS_FTRACE_OPS |
| 123 | 123 | static void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, |
| 124 | − struct ftrace_ops *op, struct pt_regs *regs); | |
| 124 | + struct ftrace_ops *op, struct ftrace_regs *fregs); | |
| 125 | 125 | #else |
| 126 | 126 | /* See comment below, where ftrace_ops_list_func is defined */ |
| 127 | 127 | static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip); |
| @@ -140,7 +140,7 @@ static inline void ftrace_ops_init(struct ftrace_ops *ops) · 12 unmodified lines | ||
| 140 | 140 | } |
| 141 | 141 | |
| 142 | 142 | static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip, |
| 143 | − struct ftrace_ops *op, struct pt_regs *regs) | |
| 143 | + struct ftrace_ops *op, struct ftrace_regs *fregs) | |
| 144 | 144 | { |
| 145 | 145 | struct trace_array *tr = op->private; |
| 146 | 146 | int pid; |
| @@ -154,7 +154,7 @@ static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip, · 7 unmodified lines | ||
| 154 | 154 | return; |
| 155 | 155 | } |
| 156 | 156 | |
| 157 | − op->saved_func(ip, parent_ip, op, regs); | |
| 157 | + op->saved_func(ip, parent_ip, op, fregs); | |
| 158 | 158 | } |
| 159 | 159 | |
| 160 | 160 | static void ftrace_sync_ipi(void *data) |
| @@ -754,7 +754,7 @@ ftrace_profile_alloc(struct ftrace_profile_stat *stat, unsigned long ip) · 593 unmodified lines | ||
| 754 | 754 | |
| 755 | 755 | static void |
| 756 | 756 | function_profile_call(unsigned long ip, unsigned long parent_ip, |
| 757 | − struct ftrace_ops *ops, struct pt_regs *regs) | |
| 757 | + struct ftrace_ops *ops, struct ftrace_regs *fregs) | |
| 758 | 758 | { |
| 759 | 759 | struct ftrace_profile_stat *stat; |
| 760 | 760 | struct ftrace_profile *rec; |
| @@ -2143,6 +2143,7 @@ static int ftrace_check_record(struct dyn_ftrace *rec, bool enable, bool update) · 1382 unmodified lines | ||
| 2143 | 2143 | else |
| 2144 | 2144 | rec->flags &= ~FTRACE_FL_TRAMP_EN; |
| 2145 | 2145 | } |
| 2146 | + | |
| 2146 | 2147 | if (flag & FTRACE_FL_DIRECT) { |
| 2147 | 2148 | /* |
| 2148 | 2149 | * If there's only one user (direct_ops helper) |
| @@ -2368,8 +2369,9 @@ unsigned long ftrace_find_rec_direct(unsigned long ip) · 219 unmodified lines | ||
| 2368 | 2369 | } |
| 2369 | 2370 | |
| 2370 | 2371 | static void call_direct_funcs(unsigned long ip, unsigned long pip, |
| 2371 | − struct ftrace_ops *ops, struct pt_regs *regs) | |
| 2372 | + struct ftrace_ops *ops, struct ftrace_regs *fregs) | |
| 2372 | 2373 | { |
| 2374 | + struct pt_regs *regs = ftrace_get_regs(fregs); | |
| 2373 | 2375 | unsigned long addr; |
| 2374 | 2376 | |
| 2375 | 2377 | addr = ftrace_find_rec_direct(ip); |
| @@ -4292,7 +4294,7 @@ static int __init ftrace_mod_cmd_init(void) · 1916 unmodified lines | ||
| 4292 | 4294 | core_initcall(ftrace_mod_cmd_init); |
| 4293 | 4295 | |
| 4294 | 4296 | static void function_trace_probe_call(unsigned long ip, unsigned long parent_ip, |
| 4295 | − struct ftrace_ops *op, struct pt_regs *pt_regs) | |
| 4297 | + struct ftrace_ops *op, struct ftrace_regs *fregs) | |
| 4296 | 4298 | { |
| 4297 | 4299 | struct ftrace_probe_ops *probe_ops; |
| 4298 | 4300 | struct ftrace_func_probe *probe; |
| @@ -6911,8 +6913,9 @@ void ftrace_reset_array_ops(struct trace_array *tr) · 2612 unmodified lines | ||
| 6911 | 6913 | |
| 6912 | 6914 | static nokprobe_inline void |
| 6913 | 6915 | __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, |
| 6914 | − struct ftrace_ops *ignored, struct pt_regs *regs) | |
| 6916 | + struct ftrace_ops *ignored, struct ftrace_regs *fregs) | |
| 6915 | 6917 | { |
| 6918 | + struct pt_regs *regs = ftrace_get_regs(fregs); | |
| 6916 | 6919 | struct ftrace_ops *op; |
| 6917 | 6920 | int bit; |
| 6918 | 6921 | |
| @@ -6945,7 +6948,7 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, · 26 unmodified lines | ||
| 6945 | 6948 | pr_warn("op=%p %pS\n", op, op); |
| 6946 | 6949 | goto out; |
| 6947 | 6950 | } |
| 6948 | − op->func(ip, parent_ip, op, regs); | |
| 6951 | + op->func(ip, parent_ip, op, fregs); | |
| 6949 | 6952 | } |
| 6950 | 6953 | } while_for_each_ftrace_op(op); |
| 6951 | 6954 | out: |
| @@ -6968,9 +6971,9 @@ out: · 16 unmodified lines | ||
| 6968 | 6971 | */ |
| 6969 | 6972 | #if ARCH_SUPPORTS_FTRACE_OPS |
| 6970 | 6973 | static void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, |
| 6971 | − struct ftrace_ops *op, struct pt_regs *regs) | |
| 6974 | + struct ftrace_ops *op, struct ftrace_regs *fregs) | |
| 6972 | 6975 | { |
| 6973 | − __ftrace_ops_list_func(ip, parent_ip, NULL, regs); | |
| 6976 | + __ftrace_ops_list_func(ip, parent_ip, NULL, fregs); | |
| 6974 | 6977 | } |
| 6975 | 6978 | NOKPROBE_SYMBOL(ftrace_ops_list_func); |
| 6976 | 6979 | #else |
| @@ -6987,7 +6990,7 @@ NOKPROBE_SYMBOL(ftrace_ops_no_ops); · 10 unmodified lines | ||
| 6987 | 6990 | * this function will be called by the mcount trampoline. |
| 6988 | 6991 | */ |
| 6989 | 6992 | static void ftrace_ops_assist_func(unsigned long ip, unsigned long parent_ip, |
| 6990 | − struct ftrace_ops *op, struct pt_regs *regs) | |
| 6993 | + struct ftrace_ops *op, struct ftrace_regs *fregs) | |
| 6991 | 6994 | { |
| 6992 | 6995 | int bit; |
| 6993 | 6996 | |
| @@ -6998,7 +7001,7 @@ static void ftrace_ops_assist_func(unsigned long ip, unsigned long parent_ip, · 4 unmodified lines | ||
| 6998 | 7001 | preempt_disable_notrace(); |
| 6999 | 7002 | |
| 7000 | 7003 | if (!(op->flags & FTRACE_OPS_FL_RCU) || rcu_is_watching()) |
| 7001 | − op->func(ip, parent_ip, op, regs); | |
| 7004 | + op->func(ip, parent_ip, op, fregs); | |
| 7002 | 7005 | |
| 7003 | 7006 | preempt_enable_notrace(); |
| 7004 | 7007 | trace_clear_recursion(bit); |
| @@ -432,7 +432,7 @@ NOKPROBE_SYMBOL(perf_trace_buf_update); · 431 unmodified lines | ||
| 432 | 432 | #ifdef CONFIG_FUNCTION_TRACER |
| 433 | 433 | static void |
| 434 | 434 | perf_ftrace_function_call(unsigned long ip, unsigned long parent_ip, |
| 435 | − struct ftrace_ops *ops, struct pt_regs *pt_regs) | |
| 435 | + struct ftrace_ops *ops, struct ftrace_regs *fregs) | |
| 436 | 436 | { |
| 437 | 437 | struct ftrace_entry *entry; |
| 438 | 438 | struct perf_event *event; |
| @@ -3673,7 +3673,7 @@ static struct trace_event_file event_trace_file __initdata; · 3672 unmodified lines | ||
| 3673 | 3673 | |
| 3674 | 3674 | static void __init |
| 3675 | 3675 | function_test_events_call(unsigned long ip, unsigned long parent_ip, |
| 3676 | − struct ftrace_ops *op, struct pt_regs *pt_regs) | |
| 3676 | + struct ftrace_ops *op, struct ftrace_regs *regs) | |
| 3677 | 3677 | { |
| 3678 | 3678 | struct trace_buffer *buffer; |
| 3679 | 3679 | struct ring_buffer_event *event; |
| @@ -23,10 +23,10 @@ static void tracing_start_function_trace(struct trace_array *tr); · 22 unmodified lines | ||
| 23 | 23 | static void tracing_stop_function_trace(struct trace_array *tr); |
| 24 | 24 | static void |
| 25 | 25 | function_trace_call(unsigned long ip, unsigned long parent_ip, |
| 26 | − struct ftrace_ops *op, struct pt_regs *pt_regs); | |
| 26 | + struct ftrace_ops *op, struct ftrace_regs *fregs); | |
| 27 | 27 | static void |
| 28 | 28 | function_stack_trace_call(unsigned long ip, unsigned long parent_ip, |
| 29 | − struct ftrace_ops *op, struct pt_regs *pt_regs); | |
| 29 | + struct ftrace_ops *op, struct ftrace_regs *fregs); | |
| 30 | 30 | static struct tracer_flags func_flags; |
| 31 | 31 | |
| 32 | 32 | /* Our option */ |
| @@ -89,7 +89,6 @@ void ftrace_destroy_function_files(struct trace_array *tr) · 56 unmodified lines | ||
| 89 | 89 | static int function_trace_init(struct trace_array *tr) |
| 90 | 90 | { |
| 91 | 91 | ftrace_func_t func; |
| 92 | − | |
| 93 | 92 | /* |
| 94 | 93 | * Instance trace_arrays get their ops allocated |
| 95 | 94 | * at instance creation. Unless it failed |
| @@ -129,7 +128,7 @@ static void function_trace_start(struct trace_array *tr) · 33 unmodified lines | ||
| 129 | 128 | |
| 130 | 129 | static void |
| 131 | 130 | function_trace_call(unsigned long ip, unsigned long parent_ip, |
| 132 | − struct ftrace_ops *op, struct pt_regs *pt_regs) | |
| 131 | + struct ftrace_ops *op, struct ftrace_regs *fregs) | |
| 133 | 132 | { |
| 134 | 133 | struct trace_array *tr = op->private; |
| 135 | 134 | struct trace_array_cpu *data; |
| @@ -178,7 +177,7 @@ function_trace_call(unsigned long ip, unsigned long parent_ip, · 42 unmodified lines | ||
| 178 | 177 | |
| 179 | 178 | static void |
| 180 | 179 | function_stack_trace_call(unsigned long ip, unsigned long parent_ip, |
| 181 | − struct ftrace_ops *op, struct pt_regs *pt_regs) | |
| 180 | + struct ftrace_ops *op, struct ftrace_regs *fregs) | |
| 182 | 181 | { |
| 183 | 182 | struct trace_array *tr = op->private; |
| 184 | 183 | struct trace_array_cpu *data; |
| @@ -138,7 +138,7 @@ static int func_prolog_dec(struct trace_array *tr, · 137 unmodified lines | ||
| 138 | 138 | */ |
| 139 | 139 | static void |
| 140 | 140 | irqsoff_tracer_call(unsigned long ip, unsigned long parent_ip, |
| 141 | − struct ftrace_ops *op, struct pt_regs *pt_regs) | |
| 141 | + struct ftrace_ops *op, struct ftrace_regs *fregs) | |
| 142 | 142 | { |
| 143 | 143 | struct trace_array *tr = irqsoff_trace; |
| 144 | 144 | struct trace_array_cpu *data; |
| @@ -212,7 +212,7 @@ static void wakeup_print_header(struct seq_file *s) · 211 unmodified lines | ||
| 212 | 212 | */ |
| 213 | 213 | static void |
| 214 | 214 | wakeup_tracer_call(unsigned long ip, unsigned long parent_ip, |
| 215 | − struct ftrace_ops *op, struct pt_regs *pt_regs) | |
| 215 | + struct ftrace_ops *op, struct ftrace_regs *fregs) | |
| 216 | 216 | { |
| 217 | 217 | struct trace_array *tr = wakeup_trace; |
| 218 | 218 | struct trace_array_cpu *data; |
| @@ -107,7 +107,7 @@ static int trace_selftest_test_probe1_cnt; · 106 unmodified lines | ||
| 107 | 107 | static void trace_selftest_test_probe1_func(unsigned long ip, |
| 108 | 108 | unsigned long pip, |
| 109 | 109 | struct ftrace_ops *op, |
| 110 | − struct pt_regs *pt_regs) | |
| 110 | + struct ftrace_regs *fregs) | |
| 111 | 111 | { |
| 112 | 112 | trace_selftest_test_probe1_cnt++; |
| 113 | 113 | } |
| @@ -116,7 +116,7 @@ static int trace_selftest_test_probe2_cnt; · 2 unmodified lines | ||
| 116 | 116 | static void trace_selftest_test_probe2_func(unsigned long ip, |
| 117 | 117 | unsigned long pip, |
| 118 | 118 | struct ftrace_ops *op, |
| 119 | − struct pt_regs *pt_regs) | |
| 119 | + struct ftrace_regs *fregs) | |
| 120 | 120 | { |
| 121 | 121 | trace_selftest_test_probe2_cnt++; |
| 122 | 122 | } |
| @@ -125,7 +125,7 @@ static int trace_selftest_test_probe3_cnt; · 2 unmodified lines | ||
| 125 | 125 | static void trace_selftest_test_probe3_func(unsigned long ip, |
| 126 | 126 | unsigned long pip, |
| 127 | 127 | struct ftrace_ops *op, |
| 128 | − struct pt_regs *pt_regs) | |
| 128 | + struct ftrace_regs *fregs) | |
| 129 | 129 | { |
| 130 | 130 | trace_selftest_test_probe3_cnt++; |
| 131 | 131 | } |
| @@ -134,7 +134,7 @@ static int trace_selftest_test_global_cnt; · 2 unmodified lines | ||
| 134 | 134 | static void trace_selftest_test_global_func(unsigned long ip, |
| 135 | 135 | unsigned long pip, |
| 136 | 136 | struct ftrace_ops *op, |
| 137 | − struct pt_regs *pt_regs) | |
| 137 | + struct ftrace_regs *fregs) | |
| 138 | 138 | { |
| 139 | 139 | trace_selftest_test_global_cnt++; |
| 140 | 140 | } |
| @@ -143,7 +143,7 @@ static int trace_selftest_test_dyn_cnt; · 2 unmodified lines | ||
| 143 | 143 | static void trace_selftest_test_dyn_func(unsigned long ip, |
| 144 | 144 | unsigned long pip, |
| 145 | 145 | struct ftrace_ops *op, |
| 146 | − struct pt_regs *pt_regs) | |
| 146 | + struct ftrace_regs *fregs) | |
| 147 | 147 | { |
| 148 | 148 | trace_selftest_test_dyn_cnt++; |
| 149 | 149 | } |
| @@ -414,7 +414,7 @@ static int trace_selftest_recursion_cnt; · 264 unmodified lines | ||
| 414 | 414 | static void trace_selftest_test_recursion_func(unsigned long ip, |
| 415 | 415 | unsigned long pip, |
| 416 | 416 | struct ftrace_ops *op, |
| 417 | − struct pt_regs *pt_regs) | |
| 417 | + struct ftrace_regs *fregs) | |
| 418 | 418 | { |
| 419 | 419 | /* |
| 420 | 420 | * This function is registered without the recursion safe flag. |
| @@ -429,7 +429,7 @@ static void trace_selftest_test_recursion_func(unsigned long ip, · 8 unmodified lines | ||
| 429 | 429 | static void trace_selftest_test_recursion_safe_func(unsigned long ip, |
| 430 | 430 | unsigned long pip, |
| 431 | 431 | struct ftrace_ops *op, |
| 432 | − struct pt_regs *pt_regs) | |
| 432 | + struct ftrace_regs *fregs) | |
| 433 | 433 | { |
| 434 | 434 | /* |
| 435 | 435 | * We said we would provide our own recursion. By calling |
| @@ -548,9 +548,11 @@ static enum { · 112 unmodified lines | ||
| 548 | 548 | static void trace_selftest_test_regs_func(unsigned long ip, |
| 549 | 549 | unsigned long pip, |
| 550 | 550 | struct ftrace_ops *op, |
| 551 | − struct pt_regs *pt_regs) | |
| 551 | + struct ftrace_regs *fregs) | |
| 552 | 552 | { |
| 553 | − if (pt_regs) | |
| 553 | + struct pt_regs *regs = ftrace_get_regs(fregs); | |
| 554 | + | |
| 555 | + if (regs) | |
| 554 | 556 | trace_selftest_regs_stat = TRACE_SELFTEST_REGS_FOUND; |
| 555 | 557 | else |
| 556 | 558 | trace_selftest_regs_stat = TRACE_SELFTEST_REGS_NOT_FOUND; |
| @@ -290,7 +290,7 @@ static void check_stack(unsigned long ip, unsigned long *stack) · 289 unmodified lines | ||
| 290 | 290 | |
| 291 | 291 | static void |
| 292 | 292 | stack_trace_call(unsigned long ip, unsigned long parent_ip, |
| 293 | − struct ftrace_ops *op, struct pt_regs *pt_regs) | |
| 293 | + struct ftrace_ops *op, struct ftrace_regs *fregs) | |
| 294 | 294 | { |
| 295 | 295 | unsigned long stack; |
| 296 | 296 | |