Skip to content

Commit 9db05d1

Browse files
Sebastian Andrzej Siewiorrkhuangtao
Sebastian Andrzej Siewior
authored andcommittedJul 20, 2022
UPSTREAM: sched/debug: Fix preempt_disable_ip recording for preempt_disable()
The preempt_disable() invokes preempt_count_add() which saves the caller in ->preempt_disable_ip. It uses CALLER_ADDR1 which does not look for its caller but for the parent of the caller. Which means we get the correct caller for something like spin_lock() unless the architectures inlines those invocations. It is always wrong for preempt_disable() or local_bh_disable(). This patch makes the function get_lock_parent_ip() which tries CALLER_ADDR0,1,2 if the former is a locking function. This seems to record the preempt_disable() caller properly for preempt_disable() itself as well as for get_cpu_var() or local_bh_disable(). Steven asked for the get_parent_ip() -> get_lock_parent_ip() rename. Change-Id: If6552232b87834fedfecd4f9d6ca4ebb3af3b85e Signed-off-by: Sebastian Andrzej Siewior <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Mike Galbraith <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Steven Rostedt <[email protected]> Cc: Thomas Gleixner <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]> Signed-off-by: Tao Huang <[email protected]> (cherry picked from commit f904f58)
1 parent 2dff1de commit 9db05d1

File tree

4 files changed

+16
-16
lines changed

4 files changed

+16
-16
lines changed
 

‎include/linux/ftrace.h

+12
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,18 @@ static inline void __ftrace_enabled_restore(int enabled)
694694
#define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
695695
#define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
696696

697+
static inline unsigned long get_lock_parent_ip(void)
698+
{
699+
unsigned long addr = CALLER_ADDR0;
700+
701+
if (!in_lock_functions(addr))
702+
return addr;
703+
addr = CALLER_ADDR1;
704+
if (!in_lock_functions(addr))
705+
return addr;
706+
return CALLER_ADDR2;
707+
}
708+
697709
#ifdef CONFIG_IRQSOFF_TRACER
698710
extern void time_hardirqs_on(unsigned long a0, unsigned long a1);
699711
extern void time_hardirqs_off(unsigned long a0, unsigned long a1);

‎include/linux/sched.h

-2
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,6 @@ extern void update_cpu_load_nohz(void);
186186
static inline void update_cpu_load_nohz(void) { }
187187
#endif
188188

189-
extern unsigned long get_parent_ip(unsigned long addr);
190-
191189
extern void dump_cpu_task(int cpu);
192190

193191
struct seq_file;

‎kernel/sched/core.c

+2-12
Original file line numberDiff line numberDiff line change
@@ -3048,16 +3048,6 @@ u64 scheduler_tick_max_deferment(void)
30483048
}
30493049
#endif
30503050

3051-
notrace unsigned long get_parent_ip(unsigned long addr)
3052-
{
3053-
if (in_lock_functions(addr)) {
3054-
addr = CALLER_ADDR2;
3055-
if (in_lock_functions(addr))
3056-
addr = CALLER_ADDR3;
3057-
}
3058-
return addr;
3059-
}
3060-
30613051
#if defined(CONFIG_PREEMPT) && (defined(CONFIG_DEBUG_PREEMPT) || \
30623052
defined(CONFIG_PREEMPT_TRACER))
30633053

@@ -3079,7 +3069,7 @@ void preempt_count_add(int val)
30793069
PREEMPT_MASK - 10);
30803070
#endif
30813071
if (preempt_count() == val) {
3082-
unsigned long ip = get_parent_ip(CALLER_ADDR1);
3072+
unsigned long ip = get_lock_parent_ip();
30833073
#ifdef CONFIG_DEBUG_PREEMPT
30843074
current->preempt_disable_ip = ip;
30853075
#endif
@@ -3106,7 +3096,7 @@ void preempt_count_sub(int val)
31063096
#endif
31073097

31083098
if (preempt_count() == val)
3109-
trace_preempt_on(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
3099+
trace_preempt_on(CALLER_ADDR0, get_lock_parent_ip());
31103100
__preempt_count_sub(val);
31113101
}
31123102
EXPORT_SYMBOL(preempt_count_sub);

‎kernel/softirq.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,9 @@ void __local_bh_disable_ip(unsigned long ip, unsigned int cnt)
116116

117117
if (preempt_count() == cnt) {
118118
#ifdef CONFIG_DEBUG_PREEMPT
119-
current->preempt_disable_ip = get_parent_ip(CALLER_ADDR1);
119+
current->preempt_disable_ip = get_lock_parent_ip();
120120
#endif
121-
trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
121+
trace_preempt_off(CALLER_ADDR0, get_lock_parent_ip());
122122
}
123123
}
124124
EXPORT_SYMBOL(__local_bh_disable_ip);

0 commit comments

Comments
 (0)
Please sign in to comment.