aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386')
-rw-r--r--arch/i386/Kconfig.debug9
-rw-r--r--arch/i386/kernel/traps.c32
2 files changed, 36 insertions, 5 deletions
diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug
index bf32ecc9ad04..00108ba9a78d 100644
--- a/arch/i386/Kconfig.debug
+++ b/arch/i386/Kconfig.debug
@@ -31,6 +31,15 @@ config DEBUG_STACK_USAGE
31 31
32 This option will slow down process creation somewhat. 32 This option will slow down process creation somewhat.
33 33
34config STACK_BACKTRACE_COLS
35 int "Stack backtraces per line" if DEBUG_KERNEL
36 range 1 3
37 default 2
38 help
39 Selects how many stack backtrace entries per line to display.
40
41 This can save screen space when displaying traces.
42
34comment "Page alloc debug is incompatible with Software Suspend on i386" 43comment "Page alloc debug is incompatible with Software Suspend on i386"
35 depends on DEBUG_KERNEL && SOFTWARE_SUSPEND 44 depends on DEBUG_KERNEL && SOFTWARE_SUSPEND
36 45
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index b814dbdcc91e..ee61988f61b5 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -112,12 +112,30 @@ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
112 p < (void *)tinfo + THREAD_SIZE - 3; 112 p < (void *)tinfo + THREAD_SIZE - 3;
113} 113}
114 114
115static void print_addr_and_symbol(unsigned long addr, char *log_lvl) 115/*
116 * Print CONFIG_STACK_BACKTRACE_COLS address/symbol entries per line.
117 */
118static inline int print_addr_and_symbol(unsigned long addr, char *log_lvl,
119 int printed)
116{ 120{
117 printk(log_lvl); 121 if (!printed)
122 printk(log_lvl);
123
124#if CONFIG_STACK_BACKTRACE_COLS == 1
118 printk(" [<%08lx>] ", addr); 125 printk(" [<%08lx>] ", addr);
126#else
127 printk(" <%08lx> ", addr);
128#endif
119 print_symbol("%s", addr); 129 print_symbol("%s", addr);
120 printk("\n"); 130
131 printed = (printed + 1) % CONFIG_STACK_BACKTRACE_COLS;
132
133 if (printed)
134 printk(" ");
135 else
136 printk("\n");
137
138 return printed;
121} 139}
122 140
123static inline unsigned long print_context_stack(struct thread_info *tinfo, 141static inline unsigned long print_context_stack(struct thread_info *tinfo,
@@ -125,20 +143,24 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo,
125 char *log_lvl) 143 char *log_lvl)
126{ 144{
127 unsigned long addr; 145 unsigned long addr;
146 int printed = 0; /* nr of entries already printed on current line */
128 147
129#ifdef CONFIG_FRAME_POINTER 148#ifdef CONFIG_FRAME_POINTER
130 while (valid_stack_ptr(tinfo, (void *)ebp)) { 149 while (valid_stack_ptr(tinfo, (void *)ebp)) {
131 addr = *(unsigned long *)(ebp + 4); 150 addr = *(unsigned long *)(ebp + 4);
132 print_addr_and_symbol(addr, log_lvl); 151 printed = print_addr_and_symbol(addr, log_lvl, printed);
133 ebp = *(unsigned long *)ebp; 152 ebp = *(unsigned long *)ebp;
134 } 153 }
135#else 154#else
136 while (valid_stack_ptr(tinfo, stack)) { 155 while (valid_stack_ptr(tinfo, stack)) {
137 addr = *stack++; 156 addr = *stack++;
138 if (__kernel_text_address(addr)) 157 if (__kernel_text_address(addr))
139 print_addr_and_symbol(addr, log_lvl); 158 printed = print_addr_and_symbol(addr, log_lvl, printed);
140 } 159 }
141#endif 160#endif
161 if (printed)
162 printk("\n");
163
142 return ebp; 164 return ebp;
143} 165}
144 166