aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/kernel/stacktrace.c11
-rw-r--r--arch/s390/kernel/stacktrace.c17
-rw-r--r--arch/x86_64/kernel/stacktrace.c14
-rw-r--r--include/linux/stacktrace.h7
-rw-r--r--kernel/lockdep.c5
5 files changed, 24 insertions, 30 deletions
diff --git a/arch/i386/kernel/stacktrace.c b/arch/i386/kernel/stacktrace.c
index e62a037ab399..ae3c32a87add 100644
--- a/arch/i386/kernel/stacktrace.c
+++ b/arch/i386/kernel/stacktrace.c
@@ -61,12 +61,8 @@ save_context_stack(struct stack_trace *trace, unsigned int skip,
61 61
62/* 62/*
63 * Save stack-backtrace addresses into a stack_trace buffer. 63 * Save stack-backtrace addresses into a stack_trace buffer.
64 * If all_contexts is set, all contexts (hardirq, softirq and process)
65 * are saved. If not set then only the current context is saved.
66 */ 64 */
67void save_stack_trace(struct stack_trace *trace, 65void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
68 struct task_struct *task, int all_contexts,
69 unsigned int skip)
70{ 66{
71 unsigned long ebp; 67 unsigned long ebp;
72 unsigned long *stack = &ebp; 68 unsigned long *stack = &ebp;
@@ -85,10 +81,9 @@ void save_stack_trace(struct stack_trace *trace,
85 struct thread_info *context = (struct thread_info *) 81 struct thread_info *context = (struct thread_info *)
86 ((unsigned long)stack & (~(THREAD_SIZE - 1))); 82 ((unsigned long)stack & (~(THREAD_SIZE - 1)));
87 83
88 ebp = save_context_stack(trace, skip, context, stack, ebp); 84 ebp = save_context_stack(trace, trace->skip, context, stack, ebp);
89 stack = (unsigned long *)context->previous_esp; 85 stack = (unsigned long *)context->previous_esp;
90 if (!all_contexts || !stack || 86 if (!stack || trace->nr_entries >= trace->max_entries)
91 trace->nr_entries >= trace->max_entries)
92 break; 87 break;
93 trace->entries[trace->nr_entries++] = ULONG_MAX; 88 trace->entries[trace->nr_entries++] = ULONG_MAX;
94 if (trace->nr_entries >= trace->max_entries) 89 if (trace->nr_entries >= trace->max_entries)
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
index de83f38288d0..d9428a0fc8fb 100644
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -59,9 +59,7 @@ static inline unsigned long save_context_stack(struct stack_trace *trace,
59 } 59 }
60} 60}
61 61
62void save_stack_trace(struct stack_trace *trace, 62void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
63 struct task_struct *task, int all_contexts,
64 unsigned int skip)
65{ 63{
66 register unsigned long sp asm ("15"); 64 register unsigned long sp asm ("15");
67 unsigned long orig_sp; 65 unsigned long orig_sp;
@@ -69,22 +67,23 @@ void save_stack_trace(struct stack_trace *trace,
69 sp &= PSW_ADDR_INSN; 67 sp &= PSW_ADDR_INSN;
70 orig_sp = sp; 68 orig_sp = sp;
71 69
72 sp = save_context_stack(trace, &skip, sp, 70 sp = save_context_stack(trace, &trace->skip, sp,
73 S390_lowcore.panic_stack - PAGE_SIZE, 71 S390_lowcore.panic_stack - PAGE_SIZE,
74 S390_lowcore.panic_stack); 72 S390_lowcore.panic_stack);
75 if ((sp != orig_sp) && !all_contexts) 73 if ((sp != orig_sp) && !trace->all_contexts)
76 return; 74 return;
77 sp = save_context_stack(trace, &skip, sp, 75 sp = save_context_stack(trace, &trace->skip, sp,
78 S390_lowcore.async_stack - ASYNC_SIZE, 76 S390_lowcore.async_stack - ASYNC_SIZE,
79 S390_lowcore.async_stack); 77 S390_lowcore.async_stack);
80 if ((sp != orig_sp) && !all_contexts) 78 if ((sp != orig_sp) && !trace->all_contexts)
81 return; 79 return;
82 if (task) 80 if (task)
83 save_context_stack(trace, &skip, sp, 81 save_context_stack(trace, &trace->skip, sp,
84 (unsigned long) task_stack_page(task), 82 (unsigned long) task_stack_page(task),
85 (unsigned long) task_stack_page(task) + THREAD_SIZE); 83 (unsigned long) task_stack_page(task) + THREAD_SIZE);
86 else 84 else
87 save_context_stack(trace, &skip, sp, S390_lowcore.thread_info, 85 save_context_stack(trace, &trace->skip, sp,
86 S390_lowcore.thread_info,
88 S390_lowcore.thread_info + THREAD_SIZE); 87 S390_lowcore.thread_info + THREAD_SIZE);
89 return; 88 return;
90} 89}
diff --git a/arch/x86_64/kernel/stacktrace.c b/arch/x86_64/kernel/stacktrace.c
index 32cf55eb9af8..1c022af8fe1e 100644
--- a/arch/x86_64/kernel/stacktrace.c
+++ b/arch/x86_64/kernel/stacktrace.c
@@ -109,9 +109,10 @@ out_restore:
109 * Save stack-backtrace addresses into a stack_trace buffer: 109 * Save stack-backtrace addresses into a stack_trace buffer:
110 */ 110 */
111static inline unsigned long 111static inline unsigned long
112save_context_stack(struct stack_trace *trace, unsigned int skip, 112save_context_stack(struct stack_trace *trace,
113 unsigned long stack, unsigned long stack_end) 113 unsigned long stack, unsigned long stack_end)
114{ 114{
115 int skip = trace->skip;
115 unsigned long addr; 116 unsigned long addr;
116 117
117#ifdef CONFIG_FRAME_POINTER 118#ifdef CONFIG_FRAME_POINTER
@@ -159,12 +160,8 @@ save_context_stack(struct stack_trace *trace, unsigned int skip,
159 160
160/* 161/*
161 * Save stack-backtrace addresses into a stack_trace buffer. 162 * Save stack-backtrace addresses into a stack_trace buffer.
162 * If all_contexts is set, all contexts (hardirq, softirq and process)
163 * are saved. If not set then only the current context is saved.
164 */ 163 */
165void save_stack_trace(struct stack_trace *trace, 164void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
166 struct task_struct *task, int all_contexts,
167 unsigned int skip)
168{ 165{
169 unsigned long stack = (unsigned long)&stack; 166 unsigned long stack = (unsigned long)&stack;
170 int i, nr_stacks = 0, stacks_done[MAX_STACKS]; 167 int i, nr_stacks = 0, stacks_done[MAX_STACKS];
@@ -207,9 +204,8 @@ void save_stack_trace(struct stack_trace *trace,
207 return; 204 return;
208 stacks_done[nr_stacks] = stack_end; 205 stacks_done[nr_stacks] = stack_end;
209 206
210 stack = save_context_stack(trace, skip, stack, stack_end); 207 stack = save_context_stack(trace, stack, stack_end);
211 if (!all_contexts || !stack || 208 if (!stack || trace->nr_entries >= trace->max_entries)
212 trace->nr_entries >= trace->max_entries)
213 return; 209 return;
214 trace->entries[trace->nr_entries++] = ULONG_MAX; 210 trace->entries[trace->nr_entries++] = ULONG_MAX;
215 if (trace->nr_entries >= trace->max_entries) 211 if (trace->nr_entries >= trace->max_entries)
diff --git a/include/linux/stacktrace.h b/include/linux/stacktrace.h
index 9cc81e572224..50e2b01e517c 100644
--- a/include/linux/stacktrace.h
+++ b/include/linux/stacktrace.h
@@ -5,15 +5,16 @@
5struct stack_trace { 5struct stack_trace {
6 unsigned int nr_entries, max_entries; 6 unsigned int nr_entries, max_entries;
7 unsigned long *entries; 7 unsigned long *entries;
8 int skip; /* input argument: How many entries to skip */
9 int all_contexts; /* input argument: if true do than one stack */
8}; 10};
9 11
10extern void save_stack_trace(struct stack_trace *trace, 12extern void save_stack_trace(struct stack_trace *trace,
11 struct task_struct *task, int all_contexts, 13 struct task_struct *task);
12 unsigned int skip);
13 14
14extern void print_stack_trace(struct stack_trace *trace, int spaces); 15extern void print_stack_trace(struct stack_trace *trace, int spaces);
15#else 16#else
16# define save_stack_trace(trace, task, all, skip) do { } while (0) 17# define save_stack_trace(trace, task) do { } while (0)
17# define print_stack_trace(trace) do { } while (0) 18# define print_stack_trace(trace) do { } while (0)
18#endif 19#endif
19 20
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 9bad17884513..900b4cb1a024 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -224,7 +224,10 @@ static int save_trace(struct stack_trace *trace)
224 trace->max_entries = MAX_STACK_TRACE_ENTRIES - nr_stack_trace_entries; 224 trace->max_entries = MAX_STACK_TRACE_ENTRIES - nr_stack_trace_entries;
225 trace->entries = stack_trace + nr_stack_trace_entries; 225 trace->entries = stack_trace + nr_stack_trace_entries;
226 226
227 save_stack_trace(trace, NULL, 0, 3); 227 trace->skip = 3;
228 trace->all_contexts = 0;
229
230 save_stack_trace(trace, NULL);
228 231
229 trace->max_entries = trace->nr_entries; 232 trace->max_entries = trace->nr_entries;
230 233