--- /dev/null
+Index: linux/arch/i386/kernel/traps.c
+===================================================================
+RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/kernel/traps.c,v
+retrieving revision 1.3.6.4
+retrieving revision 1.3.6.2.2.5
+diff -u -r1.3.6.4 -r1.3.6.2.2.5
+--- linux/arch/i386/kernel/traps.c 3 Dec 2003 21:39:03 -0000 1.3.6.4
++++ linux/arch/i386/kernel/traps.c 3 Oct 2003 22:45:43 -0000 1.3.6.2.2.5
+@@ -133,6 +137,80 @@
+
+ #endif
+
++#if CONFIG_FRAME_POINTER
++void show_stack_frame_params (int param_count, unsigned long params[])
++{
++ int i;
++ unsigned long *p, task_addr, stack_base;
++
++ if (param_count <= 0)
++ return;
++
++ task_addr = (unsigned long) current;
++ stack_base = task_addr + THREAD_SIZE - 1;
++
++ printk(" (");
++
++ for (i = 0, p = params;
++ ((param_count - i) > 1) && (p >= task_addr) && (p <= stack_base);
++ i++, p++) {
++ printk("0x%x, ", *p);
++
++ if ((i % 4) == 3)
++ printk("\n ");
++ }
++
++ if ((p >= task_addr) && (p <= stack_base))
++ printk("0x%x)\n", *p);
++}
++
++void frame_pointer_walk(unsigned long *stack)
++{
++ int i;
++ unsigned long addr, task_addr, *frame_ptr, *next_frame_ptr, *eip_ptr,
++ eip, stack_base;
++ /* static to not take up stackspace; if we race here too bad */
++ static char buffer[512];
++
++ addr = (unsigned long) stack;
++ task_addr = (unsigned long) current;
++ stack_base = task_addr + THREAD_SIZE - 1;
++
++ /* Simply return if we are doing a stack trace for any task other
++ * than the currently executing task. To trace another task, we
++ * would need an %ebp register value for that task.
++ */
++ if (((addr < task_addr) || (addr > stack_base))) {
++ return;
++ }
++
++ frame_ptr = (unsigned long *) (&stack - 2);
++
++ for (; ; ) {
++ next_frame_ptr = (unsigned long *) (*frame_ptr);
++ addr = (unsigned long) next_frame_ptr;
++
++ /* Stop when we reach a frame pointer that points to a
++ * location clearly outside our own kernel stack.
++ */
++ if ((addr < task_addr) || (addr > stack_base))
++ break;
++
++ eip_ptr = frame_ptr + 1;
++ eip = *eip_ptr;
++
++ if (kernel_text_address(eip)) {
++ lookup_symbol(eip, buffer, 512);
++ show_stack_frame_params(4, frame_ptr + 2);
++ printk("[<%08lx>] %s (0x%x)\n", eip, buffer,
++ eip_ptr);
++ }
++
++ frame_ptr = next_frame_ptr;
++ }
++}
++#endif
++
+ void show_trace(unsigned long * stack)
+ {
+ #if !CONFIG_FRAME_POINTER
+@@ -145,29 +223,20 @@
+ if (!stack)
+ stack = (unsigned long*)&stack;
+
+- printk("Call Trace: ");
++ printk("Call Trace:\n");
+ /*
+ * If we have frame pointers then use them to get
+ * a 100% exact backtrace, up until the entry frame:
+ */
+ #if CONFIG_FRAME_POINTER
+-#define DO(n) \
+- addr = (int)__builtin_return_address(n); \
+- if (!kernel_text_address(addr)) \
+- goto out; \
+- lookup_symbol(addr, buffer, 512); \
+- printk("[<%08lx>] %s\n", addr, buffer);
+-
+- DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(7); DO(8); DO(9);
+- DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); DO(17); DO(18); DO(19);
+-out:
++ frame_pointer_walk(stack);
+ #else
+ i = 1;
+ while (((long) stack & (THREAD_SIZE-1)) != 0) {
+ addr = *stack++;
+ if (kernel_text_address(addr)) {
+ lookup_symbol(addr, buffer, 512);
+- printk("[<%08lx>] %s (0x%p)\n", addr,buffer,stack-1);
++ printk("[<%08lx>] %s (0x%x)\n", addr,buffer,stack-1);
+ i++;
+ }
+ }
+@@ -242,7 +305,7 @@
+ lookup_symbol(regs->eip, buffer, 512);
+ printk("CPU: %d\nEIP: %04x:[<%08lx>] %s\nEFLAGS: %08lx\n",
+ smp_processor_id(), 0xffff & regs->xcs, regs->eip, print_tainted(), regs->eflags);
+- printk("\nEIP is at %s (" UTS_RELEASE ARCHIT ")\n",buffer);
++ printk("\nEIP is at %s (" UTS_RELEASE ")\n",buffer);
+ printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
+ regs->eax, regs->ebx, regs->ecx, regs->edx);
+ printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
--- /dev/null
+Index: linux/arch/i386/kernel/traps.c===================================================================
+RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/kernel/traps.c,v
+retrieving revision 1.3.6.2.2.11
+retrieving revision 1.3.6.2.2.12
+Index: linux-2.4.21/arch/i386/kernel/traps.c
+===================================================================
+--- linux-2.4.21.orig/arch/i386/kernel/traps.c 2004-11-01 22:00:55.000000000 -0500
++++ linux-2.4.21/arch/i386/kernel/traps.c 2004-11-02 14:20:54.000000000 -0500
+@@ -133,6 +133,30 @@
+
+ #endif
+
++void scan_stack (unsigned long *stack)
++{
++ int i;
++ unsigned long addr;
++ /* static to not take up stackspace */
++ static char buffer[NR_CPUS][512], *bufp;
++
++ bufp = buffer[smp_processor_id()];
++
++ /*
++ * If we have frame pointers then use them to get
++ * a 100% exact backtrace, up until the entry frame:
++ */
++ i = 1;
++ while (((long) stack & (THREAD_SIZE-1)) != 0) {
++ addr = *stack++;
++ if (kernel_text_address(addr)) {
++ lookup_symbol(addr, bufp, 512);
++ printk("[<%08lx>] %s (0x%p)\n", addr,bufp,stack-1);
++ i++;
++ }
++ }
++}
++
+ #if CONFIG_FRAME_POINTER
+ void show_stack_frame_params (int param_count, unsigned long params[])
+ {
+@@ -160,27 +184,23 @@
+ printk("0x%x)\n", *p);
+ }
+
+-void frame_pointer_walk(unsigned long *stack)
++/* Display a stack trace for the currently executing task. The 'dummy'
++ * parameter serves a purpose although its value is unused. We use the
++ * address of 'dummy' as a reference point for finding the saved %ebp register
++ * value on the stack.
++ */
++void frame_pointer_walk (void *dummy)
+ {
+ int i;
+ unsigned long addr, task_addr, *frame_ptr, *next_frame_ptr, *eip_ptr,
+ eip, stack_base;
+- /* static to not take up stackspace; if we race here too bad */
+- static char buffer[512];
++ /* static to not take up stackspace */
++ static char buffer[NR_CPUS][512], *bufp;
+
+- addr = (unsigned long) stack;
++ bufp = buffer[smp_processor_id()];
+ task_addr = (unsigned long) current;
+ stack_base = task_addr + THREAD_SIZE - 1;
+-
+- /* Simply return if we are doing a stack trace for any task other
+- * than the currently executing task. To trace another task, we
+- * would need an %ebp register value for that task.
+- */
+- if (((addr < task_addr) || (addr > stack_base))) {
+- return;
+- }
+-
+- frame_ptr = (unsigned long *) (&stack - 2);
++ frame_ptr = (unsigned long *) (&dummy - 2);
+
+ for (; ; ) {
+ next_frame_ptr = (unsigned long *) (*frame_ptr);
+@@ -196,50 +216,58 @@
+ eip = *eip_ptr;
+
+ if (kernel_text_address(eip)) {
+- lookup_symbol(eip, buffer, 512);
++ lookup_symbol(eip, bufp, 512);
+ show_stack_frame_params(4, frame_ptr + 2);
+- printk("[<%08lx>] %s (0x%x)\n", eip, buffer,
++ printk("[<%08lx>] %s (0x%x)\n", eip, bufp,
+ eip_ptr);
+ }
+
+ frame_ptr = next_frame_ptr;
+ }
+ }
+-#endif
++
++typedef void (*stack_trace_fn_t) (unsigned long *stack);
+
+ void show_trace(unsigned long * stack)
+ {
+-#if !CONFIG_FRAME_POINTER
+- int i;
+-#endif
+- unsigned long addr;
+- /* static to not take up stackspace; if we race here too bad */
+- static char buffer[512];
++ static const stack_trace_fn_t trace_fn_vector[] =
++ { scan_stack, frame_pointer_walk };
++ unsigned long addr, task_addr, stack_base;
++ int task_is_current;
+
+ if (!stack)
+ stack = (unsigned long*)&stack;
+
+ printk("Call Trace:\n");
+- /*
+- * If we have frame pointers then use them to get
+- * a 100% exact backtrace, up until the entry frame:
++ addr = (unsigned long) stack;
++ task_addr = (unsigned long) current;
++ stack_base = task_addr + THREAD_SIZE - 1;
++ task_is_current = (addr >= task_addr) && (addr <= stack_base);
++
++ /* We may use frame pointers to do a stack trace only if the current
++ * task is being traced. Tracing some other task in this manner
++ * would require a saved %ebp register value. Perhaps in the future
++ * I'll consider providing a means of obtaining this.
+ */
+-#if CONFIG_FRAME_POINTER
+- frame_pointer_walk(stack);
+-#else
+- i = 1;
+- while (((long) stack & (THREAD_SIZE-1)) != 0) {
+- addr = *stack++;
+- if (kernel_text_address(addr)) {
+- lookup_symbol(addr, buffer, 512);
+- printk("[<%08lx>] %s (0x%x)\n", addr,buffer,stack-1);
+- i++;
+- }
+- }
+-#endif
++ trace_fn_vector[task_is_current](stack);
++
+ printk("\n");
+ }
+
++#else /* CONFIG_FRAME_POINTER */
++
++void show_trace(unsigned long * stack)
++{
++ if (!stack)
++ stack = (unsigned long*)&stack;
++
++ printk("Call Trace:\n");
++ scan_stack(stack);
++ printk("\n");
++}
++
++#endif /* CONFIG_FRAME_POINTER */
++
+ void show_trace_task(struct task_struct *tsk)
+ {
+ unsigned long esp = tsk->thread.esp;
+Index: linux-2.4.21/include/asm-i386/hw_irq.h
+===================================================================
+--- linux-2.4.21.orig/include/asm-i386/hw_irq.h 2004-11-01 21:59:54.000000000 -0500
++++ linux-2.4.21/include/asm-i386/hw_irq.h 2004-11-02 14:20:03.000000000 -0500
+@@ -153,6 +153,9 @@
+ /* there is a second layer of macro just to get the symbolic
+ name for the vector evaluated. This change is for RTLinux */
+ #define BUILD_SMP_INTERRUPT(x,v) XBUILD_SMP_INTERRUPT(x,v)
++
++#if CONFIG_X86_HIGH_ENTRY
++
+ #define XBUILD_SMP_INTERRUPT(x,v)\
+ asmlinkage void x(void); \
+ asmlinkage void call_##x(void); \
+@@ -165,7 +168,26 @@
+ "movl $"SYMBOL_NAME_STR(smp_##x)", %ebp; call *%ebp\n\t" \
+ "jmp ret_from_intr; .previous\n");
+
++#else
++
++#define XBUILD_SMP_INTERRUPT(x,v)\
++asmlinkage void x(void); \
++asmlinkage void call_##x(void); \
++__asm__( \
++".section .entry.text,\"ax\"\n"__ALIGN_STR"\n" \
++SYMBOL_NAME_STR(x) ":\n\t" \
++ "pushl $"#v"-256\n\t" \
++ SAVE_ALL_SWITCH \
++ SYMBOL_NAME_STR(call_##x)":\n\t" \
++ "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
++ "jmp ret_from_intr; .previous\n");
++
++#endif
++
+ #define BUILD_SMP_TIMER_INTERRUPT(x,v) XBUILD_SMP_TIMER_INTERRUPT(x,v)
++
++#if CONFIG_X86_HIGH_ENTRY
++
+ #define XBUILD_SMP_TIMER_INTERRUPT(x,v) \
+ asmlinkage void x(struct pt_regs * regs); \
+ asmlinkage void call_##x(void); \
+@@ -181,6 +203,27 @@
+ "addl $4,%esp\n\t" \
+ "jmp ret_from_intr; .previous\n");
+
++#else
++
++#define XBUILD_SMP_TIMER_INTERRUPT(x,v) \
++asmlinkage void x(struct pt_regs * regs); \
++asmlinkage void call_##x(void); \
++__asm__( \
++".section .entry.text,\"ax\"\n"__ALIGN_STR"\n" \
++SYMBOL_NAME_STR(x) ":\n\t" \
++ "pushl $"#v"-256\n\t" \
++ SAVE_ALL_SWITCH \
++ "movl %esp,%eax\n\t" \
++ "pushl %eax\n\t" \
++ SYMBOL_NAME_STR(call_##x)":\n\t" \
++ "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
++ "addl $4,%esp\n\t" \
++ "jmp ret_from_intr; .previous\n");
++
++#endif
++
++#if CONFIG_X86_HIGH_ENTRY
++
+ #define BUILD_COMMON_IRQ() \
+ asmlinkage void call_do_IRQ(void); \
+ __asm__( \
+@@ -191,6 +234,20 @@
+ "movl $"SYMBOL_NAME_STR(do_IRQ)", %ebp; call *%ebp\n\t" \
+ "jmp ret_from_intr; .previous\n");
+
++#else
++
++#define BUILD_COMMON_IRQ() \
++asmlinkage void call_do_IRQ(void); \
++__asm__( \
++ ".section .entry.text,\"ax\"\n" __ALIGN_STR"\n" \
++ "common_interrupt:\n\t" \
++ SAVE_ALL_SWITCH \
++ SYMBOL_NAME_STR(call_do_IRQ)":\n\t" \
++ "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
++ "jmp ret_from_intr; .previous\n");
++
++#endif
++
+ /*
+ * subtle. orig_eax is used by the signal code to distinct between
+ * system calls and interrupted 'random user-space'. Thus we have