aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/dumpstack.c
diff options
context:
space:
mode:
authorJosh Poimboeuf <jpoimboe@redhat.com>2016-09-16 15:18:16 -0400
committerIngo Molnar <mingo@kernel.org>2016-09-20 02:29:34 -0400
commite18bcccd1a4ecb41e99678e002ef833586185bf1 (patch)
tree6cf0c83b0db2a1071e8e11014da2325da0910ae6 /arch/x86/kernel/dumpstack.c
parentec2ad9ccf12dc965cad2d367a4063f68d6561a6b (diff)
x86/dumpstack: Convert show_trace_log_lvl() to use the new unwinder
Convert show_trace_log_lvl() to use the new unwinder. dump_trace() has been deprecated. show_trace_log_lvl() is special compared to other users of the unwinder. It's the only place where both reliable *and* unreliable addresses are needed. With frame pointers enabled, most callers of the unwinder don't want to know about unreliable addresses. But in this case, when we're dumping the stack to the console because something presumably went wrong, the unreliable addresses are useful: - They show stale data on the stack which can provide useful clues. - If something goes wrong with the unwinder, or if frame pointers are corrupt or missing, all the stack addresses still get shown. So in order to show all addresses on the stack, and at the same time figure out which addresses are reliable, we have to do the scanning and the unwinding in parallel. The scanning is done with the help of get_stack_info() to traverse the stacks. The unwinding is done separately by the new unwinder. In theory we could simplify show_trace_log_lvl() by instead pushing some of this logic into the unwind code. But then we would need some kind of "fake" frame logic in the unwinder which would add a lot of complexity and wouldn't be worth it in order to support only one user. Another benefit of this approach is that once we have a DWARF unwinder, we should be able to just plug it in with minimal impact to this code. Another change here is that callers of show_trace_log_lvl() don't need to provide the 'bp' argument. The unwinder already finds the relevant frame pointer by unwinding until it reaches the first frame after the provided stack pointer. Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Byungchul Park <byungchul.park@lge.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Kees Cook <keescook@chromium.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Nilay Vaish <nilayvaish@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/703b5998604c712a1f801874b43f35d6dac52ede.1474045023.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/kernel/dumpstack.c')
-rw-r--r--arch/x86/kernel/dumpstack.c126
1 files changed, 95 insertions, 31 deletions
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index e0648f755158..c08f32ab8ace 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -17,7 +17,7 @@
17#include <linux/sysfs.h> 17#include <linux/sysfs.h>
18 18
19#include <asm/stacktrace.h> 19#include <asm/stacktrace.h>
20 20#include <asm/unwind.h>
21 21
22int panic_on_unrecovered_nmi; 22int panic_on_unrecovered_nmi;
23int panic_on_io_nmi; 23int panic_on_io_nmi;
@@ -142,56 +142,120 @@ print_context_stack_bp(struct task_struct *task,
142} 142}
143EXPORT_SYMBOL_GPL(print_context_stack_bp); 143EXPORT_SYMBOL_GPL(print_context_stack_bp);
144 144
145static int print_trace_stack(void *data, const char *name) 145void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
146 unsigned long *stack, char *log_lvl)
146{ 147{
147 printk("%s <%s> ", (char *)data, name); 148 struct unwind_state state;
148 return 0; 149 struct stack_info stack_info = {0};
149} 150 unsigned long visit_mask = 0;
151 int graph_idx = 0;
150 152
151/* 153 printk("%sCall Trace:\n", log_lvl);
152 * Print one address/symbol entries per line.
153 */
154static int print_trace_address(void *data, unsigned long addr, int reliable)
155{
156 printk_stack_address(addr, reliable, data);
157 return 0;
158}
159 154
160static const struct stacktrace_ops print_trace_ops = { 155 unwind_start(&state, task, regs, stack);
161 .stack = print_trace_stack,
162 .address = print_trace_address,
163 .walk_stack = print_context_stack,
164};
165 156
166void 157 /*
167show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, 158 * Iterate through the stacks, starting with the current stack pointer.
168 unsigned long *stack, unsigned long bp, char *log_lvl) 159 * Each stack has a pointer to the next one.
169{ 160 *
170 printk("%sCall Trace:\n", log_lvl); 161 * x86-64 can have several stacks:
171 dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl); 162 * - task stack
163 * - interrupt stack
164 * - HW exception stacks (double fault, nmi, debug, mce)
165 *
166 * x86-32 can have up to three stacks:
167 * - task stack
168 * - softirq stack
169 * - hardirq stack
170 */
171 for (; stack; stack = stack_info.next_sp) {
172 const char *str_begin, *str_end;
173
174 /*
175 * If we overflowed the task stack into a guard page, jump back
176 * to the bottom of the usable stack.
177 */
178 if (task_stack_page(task) - (void *)stack < PAGE_SIZE)
179 stack = task_stack_page(task);
180
181 if (get_stack_info(stack, task, &stack_info, &visit_mask))
182 break;
183
184 stack_type_str(stack_info.type, &str_begin, &str_end);
185 if (str_begin)
186 printk("%s <%s> ", log_lvl, str_begin);
187
188 /*
189 * Scan the stack, printing any text addresses we find. At the
190 * same time, follow proper stack frames with the unwinder.
191 *
192 * Addresses found during the scan which are not reported by
193 * the unwinder are considered to be additional clues which are
194 * sometimes useful for debugging and are prefixed with '?'.
195 * This also serves as a failsafe option in case the unwinder
196 * goes off in the weeds.
197 */
198 for (; stack < stack_info.end; stack++) {
199 unsigned long real_addr;
200 int reliable = 0;
201 unsigned long addr = *stack;
202 unsigned long *ret_addr_p =
203 unwind_get_return_address_ptr(&state);
204
205 if (!__kernel_text_address(addr))
206 continue;
207
208 if (stack == ret_addr_p)
209 reliable = 1;
210
211 /*
212 * When function graph tracing is enabled for a
213 * function, its return address on the stack is
214 * replaced with the address of an ftrace handler
215 * (return_to_handler). In that case, before printing
216 * the "real" address, we want to print the handler
217 * address as an "unreliable" hint that function graph
218 * tracing was involved.
219 */
220 real_addr = ftrace_graph_ret_addr(task, &graph_idx,
221 addr, stack);
222 if (real_addr != addr)
223 printk_stack_address(addr, 0, log_lvl);
224 printk_stack_address(real_addr, reliable, log_lvl);
225
226 if (!reliable)
227 continue;
228
229 /*
230 * Get the next frame from the unwinder. No need to
231 * check for an error: if anything goes wrong, the rest
232 * of the addresses will just be printed as unreliable.
233 */
234 unwind_next_frame(&state);
235 }
236
237 if (str_end)
238 printk("%s <%s> ", log_lvl, str_end);
239 }
172} 240}
173 241
174void show_stack(struct task_struct *task, unsigned long *sp) 242void show_stack(struct task_struct *task, unsigned long *sp)
175{ 243{
176 unsigned long bp = 0;
177
178 task = task ? : current; 244 task = task ? : current;
179 245
180 /* 246 /*
181 * Stack frames below this one aren't interesting. Don't show them 247 * Stack frames below this one aren't interesting. Don't show them
182 * if we're printing for %current. 248 * if we're printing for %current.
183 */ 249 */
184 if (!sp && task == current) { 250 if (!sp && task == current)
185 sp = get_stack_pointer(current, NULL); 251 sp = get_stack_pointer(current, NULL);
186 bp = (unsigned long)get_frame_pointer(current, NULL);
187 }
188 252
189 show_stack_log_lvl(task, NULL, sp, bp, ""); 253 show_stack_log_lvl(current, NULL, sp, "");
190} 254}
191 255
192void show_stack_regs(struct pt_regs *regs) 256void show_stack_regs(struct pt_regs *regs)
193{ 257{
194 show_stack_log_lvl(current, regs, NULL, 0, ""); 258 show_stack_log_lvl(current, regs, NULL, "");
195} 259}
196 260
197static arch_spinlock_t die_lock = __ARCH_SPIN_LOCK_UNLOCKED; 261static arch_spinlock_t die_lock = __ARCH_SPIN_LOCK_UNLOCKED;