Skip to content

Commit ce5e480

Browse files
wangyun2137rostedt
authored andcommitted
ftrace: disable preemption when recursion locked
As the documentation explained, ftrace_test_recursion_trylock() and ftrace_test_recursion_unlock() were supposed to disable and enable preemption properly, however currently this work is done outside of the function, which could be missing by mistake. And since the internal using of trace_test_and_set_recursion() and trace_clear_recursion() also require preemption disabled, we can just merge the logical. This patch will make sure the preemption has been disabled when trace_test_and_set_recursion() return bit >= 0, and trace_clear_recursion() will enable the preemption if previously enabled. Link: https://lkml.kernel.org/r/[email protected] CC: Petr Mladek <[email protected]> Cc: Guo Ren <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: "James E.J. Bottomley" <[email protected]> Cc: Helge Deller <[email protected]> Cc: Michael Ellerman <[email protected]> Cc: Benjamin Herrenschmidt <[email protected]> Cc: Paul Mackerras <[email protected]> Cc: Paul Walmsley <[email protected]> Cc: Palmer Dabbelt <[email protected]> Cc: Albert Ou <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Cc: Josh Poimboeuf <[email protected]> Cc: Jiri Kosina <[email protected]> Cc: Joe Lawrence <[email protected]> Cc: Masami Hiramatsu <[email protected]> Cc: Nicholas Piggin <[email protected]> Cc: Jisheng Zhang <[email protected]> CC: Steven Rostedt <[email protected]> CC: Miroslav Benes <[email protected]> Reported-by: Abaci <[email protected]> Suggested-by: Peter Zijlstra <[email protected]> Signed-off-by: Michael Wang <[email protected]> [ Removed extra line in comment - SDR ] Signed-off-by: Steven Rostedt (VMware) <[email protected]>
1 parent 2d2f6d4 commit ce5e480

File tree

9 files changed

+21
-32
lines changed

9 files changed

+21
-32
lines changed

arch/csky/kernel/probes/ftrace.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
1717
return;
1818

1919
regs = ftrace_get_regs(fregs);
20-
preempt_disable_notrace();
2120
p = get_kprobe((kprobe_opcode_t *)ip);
2221
if (!p) {
2322
p = get_kprobe((kprobe_opcode_t *)(ip - MCOUNT_INSN_SIZE));
@@ -57,7 +56,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
5756
__this_cpu_write(current_kprobe, NULL);
5857
}
5958
out:
60-
preempt_enable_notrace();
6159
ftrace_test_recursion_unlock(bit);
6260
}
6361
NOKPROBE_SYMBOL(kprobe_ftrace_handler);

arch/parisc/kernel/ftrace.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
211211
return;
212212

213213
regs = ftrace_get_regs(fregs);
214-
preempt_disable_notrace();
215214
p = get_kprobe((kprobe_opcode_t *)ip);
216215
if (unlikely(!p) || kprobe_disabled(p))
217216
goto out;
@@ -240,7 +239,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
240239
}
241240
__this_cpu_write(current_kprobe, NULL);
242241
out:
243-
preempt_enable_notrace();
244242
ftrace_test_recursion_unlock(bit);
245243
}
246244
NOKPROBE_SYMBOL(kprobe_ftrace_handler);

arch/powerpc/kernel/kprobes-ftrace.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ void kprobe_ftrace_handler(unsigned long nip, unsigned long parent_nip,
2626
return;
2727

2828
regs = ftrace_get_regs(fregs);
29-
preempt_disable_notrace();
3029
p = get_kprobe((kprobe_opcode_t *)nip);
3130
if (unlikely(!p) || kprobe_disabled(p))
3231
goto out;
@@ -61,7 +60,6 @@ void kprobe_ftrace_handler(unsigned long nip, unsigned long parent_nip,
6160
__this_cpu_write(current_kprobe, NULL);
6261
}
6362
out:
64-
preempt_enable_notrace();
6563
ftrace_test_recursion_unlock(bit);
6664
}
6765
NOKPROBE_SYMBOL(kprobe_ftrace_handler);

arch/riscv/kernel/probes/ftrace.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
1515
if (bit < 0)
1616
return;
1717

18-
preempt_disable_notrace();
1918
p = get_kprobe((kprobe_opcode_t *)ip);
2019
if (unlikely(!p) || kprobe_disabled(p))
2120
goto out;
@@ -52,7 +51,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
5251
__this_cpu_write(current_kprobe, NULL);
5352
}
5453
out:
55-
preempt_enable_notrace();
5654
ftrace_test_recursion_unlock(bit);
5755
}
5856
NOKPROBE_SYMBOL(kprobe_ftrace_handler);

arch/x86/kernel/kprobes/ftrace.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
2525
if (bit < 0)
2626
return;
2727

28-
preempt_disable_notrace();
2928
p = get_kprobe((kprobe_opcode_t *)ip);
3029
if (unlikely(!p) || kprobe_disabled(p))
3130
goto out;
@@ -59,7 +58,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
5958
__this_cpu_write(current_kprobe, NULL);
6059
}
6160
out:
62-
preempt_enable_notrace();
6361
ftrace_test_recursion_unlock(bit);
6462
}
6563
NOKPROBE_SYMBOL(kprobe_ftrace_handler);

include/linux/trace_recursion.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ extern void ftrace_record_recursion(unsigned long ip, unsigned long parent_ip);
155155
# define do_ftrace_record_recursion(ip, pip) do { } while (0)
156156
#endif
157157

158+
/*
159+
* Preemption is promised to be disabled when return bit >= 0.
160+
*/
158161
static __always_inline int trace_test_and_set_recursion(unsigned long ip, unsigned long pip,
159162
int start, int max)
160163
{
@@ -189,14 +192,20 @@ static __always_inline int trace_test_and_set_recursion(unsigned long ip, unsign
189192
current->trace_recursion = val;
190193
barrier();
191194

195+
preempt_disable_notrace();
196+
192197
return bit + 1;
193198
}
194199

200+
/*
201+
* Preemption will be enabled (if it was previously enabled).
202+
*/
195203
static __always_inline void trace_clear_recursion(int bit)
196204
{
197205
if (!bit)
198206
return;
199207

208+
preempt_enable_notrace();
200209
barrier();
201210
bit--;
202211
trace_recursion_clear(bit);
@@ -209,7 +218,7 @@ static __always_inline void trace_clear_recursion(int bit)
209218
* tracing recursed in the same context (normal vs interrupt),
210219
*
211220
* Returns: -1 if a recursion happened.
212-
* >= 0 if no recursion
221+
* >= 0 if no recursion.
213222
*/
214223
static __always_inline int ftrace_test_recursion_trylock(unsigned long ip,
215224
unsigned long parent_ip)

kernel/livepatch/patch.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,15 @@ static void notrace klp_ftrace_handler(unsigned long ip,
4949

5050
ops = container_of(fops, struct klp_ops, fops);
5151

52+
/*
53+
* The ftrace_test_recursion_trylock() will disable preemption,
54+
* which is required for the variant of synchronize_rcu() that is
55+
* used to allow patching functions where RCU is not watching.
56+
* See klp_synchronize_transition() for more details.
57+
*/
5258
bit = ftrace_test_recursion_trylock(ip, parent_ip);
5359
if (WARN_ON_ONCE(bit < 0))
5460
return;
55-
/*
56-
* A variant of synchronize_rcu() is used to allow patching functions
57-
* where RCU is not watching, see klp_synchronize_transition().
58-
*/
59-
preempt_disable_notrace();
6061

6162
func = list_first_or_null_rcu(&ops->func_stack, struct klp_func,
6263
stack_node);
@@ -120,7 +121,6 @@ static void notrace klp_ftrace_handler(unsigned long ip,
120121
klp_arch_set_pc(fregs, (unsigned long)func->new_func);
121122

122123
unlock:
123-
preempt_enable_notrace();
124124
ftrace_test_recursion_unlock(bit);
125125
}
126126

kernel/trace/ftrace.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7198,16 +7198,15 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
71987198
struct ftrace_ops *op;
71997199
int bit;
72007200

7201+
/*
7202+
* The ftrace_test_and_set_recursion() will disable preemption,
7203+
* which is required since some of the ops may be dynamically
7204+
* allocated, they must be freed after a synchronize_rcu().
7205+
*/
72017206
bit = trace_test_and_set_recursion(ip, parent_ip, TRACE_LIST_START, TRACE_LIST_MAX);
72027207
if (bit < 0)
72037208
return;
72047209

7205-
/*
7206-
* Some of the ops may be dynamically allocated,
7207-
* they must be freed after a synchronize_rcu().
7208-
*/
7209-
preempt_disable_notrace();
7210-
72117210
do_for_each_ftrace_op(op, ftrace_ops_list) {
72127211
/* Stub functions don't need to be called nor tested */
72137212
if (op->flags & FTRACE_OPS_FL_STUB)
@@ -7231,7 +7230,6 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
72317230
}
72327231
} while_for_each_ftrace_op(op);
72337232
out:
7234-
preempt_enable_notrace();
72357233
trace_clear_recursion(bit);
72367234
}
72377235

@@ -7279,12 +7277,9 @@ static void ftrace_ops_assist_func(unsigned long ip, unsigned long parent_ip,
72797277
if (bit < 0)
72807278
return;
72817279

7282-
preempt_disable_notrace();
7283-
72847280
if (!(op->flags & FTRACE_OPS_FL_RCU) || rcu_is_watching())
72857281
op->func(ip, parent_ip, op, fregs);
72867282

7287-
preempt_enable_notrace();
72887283
trace_clear_recursion(bit);
72897284
}
72907285
NOKPROBE_SYMBOL(ftrace_ops_assist_func);

kernel/trace/trace_functions.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -186,15 +186,13 @@ function_trace_call(unsigned long ip, unsigned long parent_ip,
186186
return;
187187

188188
trace_ctx = tracing_gen_ctx();
189-
preempt_disable_notrace();
190189

191190
cpu = smp_processor_id();
192191
data = per_cpu_ptr(tr->array_buffer.data, cpu);
193192
if (!atomic_read(&data->disabled))
194193
trace_function(tr, ip, parent_ip, trace_ctx);
195194

196195
ftrace_test_recursion_unlock(bit);
197-
preempt_enable_notrace();
198196
}
199197

200198
#ifdef CONFIG_UNWINDER_ORC
@@ -298,8 +296,6 @@ function_no_repeats_trace_call(unsigned long ip, unsigned long parent_ip,
298296
if (bit < 0)
299297
return;
300298

301-
preempt_disable_notrace();
302-
303299
cpu = smp_processor_id();
304300
data = per_cpu_ptr(tr->array_buffer.data, cpu);
305301
if (atomic_read(&data->disabled))
@@ -324,7 +320,6 @@ function_no_repeats_trace_call(unsigned long ip, unsigned long parent_ip,
324320

325321
out:
326322
ftrace_test_recursion_unlock(bit);
327-
preempt_enable_notrace();
328323
}
329324

330325
static void

0 commit comments

Comments
 (0)