1 Index: kernel/arch/i386/kernel/traps.c
2 ===================================================================
3 --- kernel.orig/arch/i386/kernel/traps.c 2006-05-26 16:12:28.000000000 -0700
4 +++ kernel/arch/i386/kernel/traps.c 2006-05-26 16:15:54.000000000 -0700
9 +void scan_stack (unsigned long *stack)
13 + /* static to not take up stackspace */
14 + static char buffer[NR_CPUS][512], *bufp;
16 + bufp = buffer[smp_processor_id()];
19 + * If we have frame pointers then use them to get
20 + * a 100% exact backtrace, up until the entry frame:
23 + while (((long) stack & (THREAD_SIZE-1)) != 0) {
25 + if (kernel_text_address(addr)) {
26 + lookup_symbol(addr, bufp, 512);
27 + printk("[<%08lx>] %s (0x%p)\n", addr,bufp,stack-1);
33 #if CONFIG_FRAME_POINTER
34 void show_stack_frame_params (int param_count, unsigned long params[])
37 printk("0x%x)\n", *p);
40 -void frame_pointer_walk(unsigned long *stack)
41 +/* Display a stack trace for the currently executing task. The 'dummy'
42 + * parameter serves a purpose although its value is unused. We use the
43 + * address of 'dummy' as a reference point for finding the saved %ebp register
44 + * value on the stack.
46 +void frame_pointer_walk (void *dummy)
49 unsigned long addr, task_addr, *frame_ptr, *next_frame_ptr, *eip_ptr,
51 - /* static to not take up stackspace; if we race here too bad */
52 - static char buffer[512];
53 + /* static to not take up stackspace */
54 + static char buffer[NR_CPUS][512], *bufp;
56 - addr = (unsigned long) stack;
57 + bufp = buffer[smp_processor_id()];
58 task_addr = (unsigned long) current;
59 stack_base = task_addr + THREAD_SIZE - 1;
61 - /* Simply return if we are doing a stack trace for any task other
62 - * than the currently executing task. To trace another task, we
63 - * would need an %ebp register value for that task.
65 - if (((addr < task_addr) || (addr > stack_base))) {
69 - frame_ptr = (unsigned long *) (&stack - 2);
70 + frame_ptr = (unsigned long *) (&dummy - 2);
73 next_frame_ptr = (unsigned long *) (*frame_ptr);
77 if (kernel_text_address(eip)) {
78 - lookup_symbol(eip, buffer, 512);
79 + lookup_symbol(eip, bufp, 512);
80 show_stack_frame_params(4, frame_ptr + 2);
81 - printk("[<%08lx>] %s (0x%x)\n", eip, buffer,
82 + printk("[<%08lx>] %s (0x%x)\n", eip, bufp,
90 +typedef void (*stack_trace_fn_t) (unsigned long *stack);
92 +#if CONFIG_FRAME_POINTER
93 void show_trace(unsigned long * stack)
95 -#if !CONFIG_FRAME_POINTER
98 - unsigned long addr, limit;
99 - /* static to not take up stackspace; if we race here too bad */
100 - static char buffer[512];
101 + static const stack_trace_fn_t trace_fn_vector[] =
102 + { scan_stack, frame_pointer_walk };
103 + unsigned long addr, task_addr, stack_base;
104 + int task_is_current;
107 stack = (unsigned long*)&stack;
109 printk("Call Trace: ");
111 - * If we have frame pointers then use them to get
112 - * a 100% exact backtrace, up until the entry frame:
114 -#if CONFIG_FRAME_POINTER
115 - frame_pointer_walk(stack);
118 - limit = ((unsigned long)stack & ~(THREAD_SIZE - 1)) + THREAD_SIZE - 3;
119 - while ((unsigned long)stack < limit) {
121 - if (kernel_text_address(addr)) {
122 - lookup_symbol(addr, buffer, 512);
123 - printk("[<%08lx>] %s (0x%x)\n", addr,buffer,stack-1);
128 + addr = (unsigned long) stack;
129 + task_addr = (unsigned long) current;
130 + stack_base = task_addr + THREAD_SIZE - 1;
131 + task_is_current = (addr >= task_addr) && (addr <= stack_base);
133 + /* We may use frame pointers to do a stack trace only if the current
134 + * task is being traced. Tracing some other task in this manner
135 + * would require a saved %ebp register value. Perhaps in the future
136 + * I'll consider providing a means of obtaining this.
138 + trace_fn_vector[task_is_current](stack);
143 +#else /* CONFIG_FRAME_POINTER */
145 +void show_trace(unsigned long * stack)
148 + stack = (unsigned long*)&stack;
150 + printk("Call Trace:\n");
155 +#endif /* CONFIG_FRAME_POINTER */
157 void show_trace_task(struct task_struct *tsk)
159 unsigned long esp = tsk->thread.esp;
160 Index: kernel/include/asm-i386/hw_irq.h
161 ===================================================================
162 --- kernel.orig/include/asm-i386/hw_irq.h 2006-05-26 16:11:33.000000000 -0700
163 +++ kernel/include/asm-i386/hw_irq.h 2006-05-26 16:13:51.000000000 -0700
165 /* there is a second layer of macro just to get the symbolic
166 name for the vector evaluated. This change is for RTLinux */
167 #define BUILD_SMP_INTERRUPT(x,v) XBUILD_SMP_INTERRUPT(x,v)
169 +#if CONFIG_X86_HIGH_ENTRY
171 #define XBUILD_SMP_INTERRUPT(x,v)\
172 asmlinkage void x(void); \
173 asmlinkage void call_##x(void); \
175 "movl $"SYMBOL_NAME_STR(smp_##x)", %ebp; call *%ebp\n\t" \
176 "jmp ret_from_intr; .previous\n");
180 +#define XBUILD_SMP_INTERRUPT(x,v)\
181 +asmlinkage void x(void); \
182 +asmlinkage void call_##x(void); \
184 +".section .entry.text,\"ax\"\n"__ALIGN_STR"\n" \
185 +SYMBOL_NAME_STR(x) ":\n\t" \
186 + "pushl $"#v"-256\n\t" \
188 + SYMBOL_NAME_STR(call_##x)":\n\t" \
189 + "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
190 + "jmp ret_from_intr; .previous\n");
194 #define BUILD_SMP_TIMER_INTERRUPT(x,v) XBUILD_SMP_TIMER_INTERRUPT(x,v)
196 +#if CONFIG_X86_HIGH_ENTRY
198 #define XBUILD_SMP_TIMER_INTERRUPT(x,v) \
199 asmlinkage void x(struct pt_regs * regs); \
200 asmlinkage void call_##x(void); \
203 "jmp ret_from_intr; .previous\n");
207 +#define XBUILD_SMP_TIMER_INTERRUPT(x,v) \
208 +asmlinkage void x(struct pt_regs * regs); \
209 +asmlinkage void call_##x(void); \
211 +".section .entry.text,\"ax\"\n"__ALIGN_STR"\n" \
212 +SYMBOL_NAME_STR(x) ":\n\t" \
213 + "pushl $"#v"-256\n\t" \
215 + "movl %esp,%eax\n\t" \
217 + SYMBOL_NAME_STR(call_##x)":\n\t" \
218 + "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
219 + "addl $4,%esp\n\t" \
220 + "jmp ret_from_intr; .previous\n");
224 +#if CONFIG_X86_HIGH_ENTRY
226 #define BUILD_COMMON_IRQ() \
227 asmlinkage void call_do_IRQ(void); \
230 "movl $"SYMBOL_NAME_STR(do_IRQ)", %ebp; call *%ebp\n\t" \
231 "jmp ret_from_intr; .previous\n");
235 +#define BUILD_COMMON_IRQ() \
236 +asmlinkage void call_do_IRQ(void); \
238 + ".section .entry.text,\"ax\"\n" __ALIGN_STR"\n" \
239 + "common_interrupt:\n\t" \
241 + SYMBOL_NAME_STR(call_do_IRQ)":\n\t" \
242 + "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
243 + "jmp ret_from_intr; .previous\n");
248 * subtle. orig_eax is used by the signal code to distinct between
249 * system calls and interrupted 'random user-space'. Thus we have