diff options
Diffstat (limited to 'kernel/trace/trace_stack.c')
-rw-r--r-- | kernel/trace/trace_stack.c | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c index dc02e29d8255..ea28e4b0ed58 100644 --- a/kernel/trace/trace_stack.c +++ b/kernel/trace/trace_stack.c | |||
@@ -20,13 +20,27 @@ | |||
20 | 20 | ||
21 | #define STACK_TRACE_ENTRIES 500 | 21 | #define STACK_TRACE_ENTRIES 500 |
22 | 22 | ||
23 | /* | ||
24 | * If fentry is used, then the function being traced will | ||
25 | * jump to fentry directly before it sets up its stack frame. | ||
26 | * We need to ignore that one and record the parent. Since | ||
27 | * the stack frame for the traced function wasn't set up yet, | ||
28 | * the stack_trace wont see the parent. That needs to be added | ||
29 | * manually to stack_dump_trace[] as the first element. | ||
30 | */ | ||
31 | #ifdef CC_USING_FENTRY | ||
32 | # define add_func 1 | ||
33 | #else | ||
34 | # define add_func 0 | ||
35 | #endif | ||
36 | |||
23 | static unsigned long stack_dump_trace[STACK_TRACE_ENTRIES+1] = | 37 | static unsigned long stack_dump_trace[STACK_TRACE_ENTRIES+1] = |
24 | { [0 ... (STACK_TRACE_ENTRIES)] = ULONG_MAX }; | 38 | { [0 ... (STACK_TRACE_ENTRIES)] = ULONG_MAX }; |
25 | static unsigned stack_dump_index[STACK_TRACE_ENTRIES]; | 39 | static unsigned stack_dump_index[STACK_TRACE_ENTRIES]; |
26 | 40 | ||
27 | static struct stack_trace max_stack_trace = { | 41 | static struct stack_trace max_stack_trace = { |
28 | .max_entries = STACK_TRACE_ENTRIES, | 42 | .max_entries = STACK_TRACE_ENTRIES - add_func, |
29 | .entries = stack_dump_trace, | 43 | .entries = &stack_dump_trace[add_func], |
30 | }; | 44 | }; |
31 | 45 | ||
32 | static unsigned long max_stack_size; | 46 | static unsigned long max_stack_size; |
@@ -40,7 +54,7 @@ int stack_tracer_enabled; | |||
40 | static int last_stack_tracer_enabled; | 54 | static int last_stack_tracer_enabled; |
41 | 55 | ||
42 | static inline void | 56 | static inline void |
43 | check_stack(unsigned long *stack) | 57 | check_stack(unsigned long ip, unsigned long *stack) |
44 | { | 58 | { |
45 | unsigned long this_size, flags; | 59 | unsigned long this_size, flags; |
46 | unsigned long *p, *top, *start; | 60 | unsigned long *p, *top, *start; |
@@ -71,6 +85,17 @@ check_stack(unsigned long *stack) | |||
71 | save_stack_trace(&max_stack_trace); | 85 | save_stack_trace(&max_stack_trace); |
72 | 86 | ||
73 | /* | 87 | /* |
88 | * When fentry is used, the traced function does not get | ||
89 | * its stack frame set up, and we lose the parent. | ||
90 | * Add that one in manally. We set up save_stack_trace() | ||
91 | * to not touch the first element in this case. | ||
92 | */ | ||
93 | if (add_func) { | ||
94 | stack_dump_trace[0] = ip; | ||
95 | max_stack_trace.nr_entries++; | ||
96 | } | ||
97 | |||
98 | /* | ||
74 | * Now find where in the stack these are. | 99 | * Now find where in the stack these are. |
75 | */ | 100 | */ |
76 | i = 0; | 101 | i = 0; |
@@ -124,7 +149,7 @@ stack_trace_call(unsigned long ip, unsigned long parent_ip, | |||
124 | if (per_cpu(trace_active, cpu)++ != 0) | 149 | if (per_cpu(trace_active, cpu)++ != 0) |
125 | goto out; | 150 | goto out; |
126 | 151 | ||
127 | check_stack(&stack); | 152 | check_stack(parent_ip, &stack); |
128 | 153 | ||
129 | out: | 154 | out: |
130 | per_cpu(trace_active, cpu)--; | 155 | per_cpu(trace_active, cpu)--; |