aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/traps_64.c
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@linux.intel.com>2008-01-30 07:33:07 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:33:07 -0500
commite4a94568b18c5d7d72741ebde5736d77d235743c (patch)
treef4dfd94e10d677483d169f6efaced214bfd036a1 /arch/x86/kernel/traps_64.c
parent5bc27dc2f55fd3043597b5a8de6536183f28a449 (diff)
x86: turn 64 bit x86 HANDLE_STACK into print_context_stack like 32 bit has
This patch turns the x86 64 bit HANDLE_STACK macro in the backtrace code into a function, just like 32 bit has. This is needed pre work in order to get exact backtraces for CONFIG_FRAME_POINTER to work. The function and it's arguments are not the same as 32 bit; due to the exception/interrupt stack way of x86-64 there are a few differences. This patch should not have any behavior changes, only code movement. Due to the fragility and importance of the backtrace code, this needs to be well reviewed and well tested before merging into mainlne. Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/kernel/traps_64.c')
-rw-r--r--arch/x86/kernel/traps_64.c74
1 files changed, 45 insertions, 29 deletions
diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c
index 62c4d8f46ee9..b8303ed95057 100644
--- a/arch/x86/kernel/traps_64.c
+++ b/arch/x86/kernel/traps_64.c
@@ -212,10 +212,46 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
212 * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack 212 * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
213 */ 213 */
214 214
215static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) 215static inline int valid_stack_ptr(struct thread_info *tinfo,
216 void *p, unsigned int size, void *end)
216{ 217{
217 void *t = (void *)tinfo; 218 void *t = (void *)tinfo;
218 return p > t && p < t + THREAD_SIZE - 3; 219 if (end) {
220 if (p < end && p >= (end-THREAD_SIZE))
221 return 1;
222 else
223 return 0;
224 }
225 return p > t && p < t + THREAD_SIZE - size;
226}
227
228static inline unsigned long print_context_stack(struct thread_info *tinfo,
229 unsigned long *stack, unsigned long bp,
230 const struct stacktrace_ops *ops, void *data,
231 unsigned long *end)
232{
233 /*
234 * Print function call entries within a stack. 'cond' is the
235 * "end of stackframe" condition, that the 'stack++'
236 * iteration will eventually trigger.
237 */
238 while (valid_stack_ptr(tinfo, stack, 3, end)) {
239 unsigned long addr = *stack++;
240 /* Use unlocked access here because except for NMIs
241 we should be already protected against module unloads */
242 if (__kernel_text_address(addr)) {
243 /*
244 * If the address is either in the text segment of the
245 * kernel, or in the region which contains vmalloc'ed
246 * memory, it *may* be the address of a calling
247 * routine; if so, print it so that someone tracing
248 * down the cause of the crash will be able to figure
249 * out the call path that was taken.
250 */
251 ops->address(data, addr, 1);
252 }
253 }
254 return bp;
219} 255}
220 256
221void dump_trace(struct task_struct *tsk, struct pt_regs *regs, 257void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
@@ -229,6 +265,7 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
229 265
230 if (!tsk) 266 if (!tsk)
231 tsk = current; 267 tsk = current;
268 tinfo = task_thread_info(tsk);
232 269
233 if (!stack) { 270 if (!stack) {
234 unsigned long dummy; 271 unsigned long dummy;
@@ -237,28 +274,6 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
237 stack = (unsigned long *)tsk->thread.sp; 274 stack = (unsigned long *)tsk->thread.sp;
238 } 275 }
239 276
240 /*
241 * Print function call entries within a stack. 'cond' is the
242 * "end of stackframe" condition, that the 'stack++'
243 * iteration will eventually trigger.
244 */
245#define HANDLE_STACK(cond) \
246 do while (cond) { \
247 unsigned long addr = *stack++; \
248 /* Use unlocked access here because except for NMIs \
249 we should be already protected against module unloads */ \
250 if (__kernel_text_address(addr)) { \
251 /* \
252 * If the address is either in the text segment of the \
253 * kernel, or in the region which contains vmalloc'ed \
254 * memory, it *may* be the address of a calling \
255 * routine; if so, print it so that someone tracing \
256 * down the cause of the crash will be able to figure \
257 * out the call path that was taken. \
258 */ \
259 ops->address(data, addr, 1); \
260 } \
261 } while (0)
262 277
263 /* 278 /*
264 * Print function call entries in all stacks, starting at the 279 * Print function call entries in all stacks, starting at the
@@ -274,7 +289,9 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
274 if (estack_end) { 289 if (estack_end) {
275 if (ops->stack(data, id) < 0) 290 if (ops->stack(data, id) < 0)
276 break; 291 break;
277 HANDLE_STACK (stack < estack_end); 292
293 print_context_stack(tinfo, stack, 0, ops,
294 data, estack_end);
278 ops->stack(data, "<EOE>"); 295 ops->stack(data, "<EOE>");
279 /* 296 /*
280 * We link to the next stack via the 297 * We link to the next stack via the
@@ -292,7 +309,8 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
292 if (stack >= irqstack && stack < irqstack_end) { 309 if (stack >= irqstack && stack < irqstack_end) {
293 if (ops->stack(data, "IRQ") < 0) 310 if (ops->stack(data, "IRQ") < 0)
294 break; 311 break;
295 HANDLE_STACK (stack < irqstack_end); 312 print_context_stack(tinfo, stack, 0, ops,
313 data, irqstack_end);
296 /* 314 /*
297 * We link to the next stack (which would be 315 * We link to the next stack (which would be
298 * the process stack normally) the last 316 * the process stack normally) the last
@@ -310,9 +328,7 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
310 /* 328 /*
311 * This handles the process stack: 329 * This handles the process stack:
312 */ 330 */
313 tinfo = task_thread_info(tsk); 331 print_context_stack(tinfo, stack, 0, ops, data, NULL);
314 HANDLE_STACK (valid_stack_ptr(tinfo, stack));
315#undef HANDLE_STACK
316 put_cpu(); 332 put_cpu();
317} 333}
318EXPORT_SYMBOL(dump_trace); 334EXPORT_SYMBOL(dump_trace);