Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 2496

kernel-2.6.18-128.1.10.el5.src.rpm

From: Don Zickus <dzickus@redhat.com>
Subject: [RHEL-5 PATCH 1/2] remove unwinder patches from x86/x86_64
Date: Tue, 2 Jan 2007 17:08:23 -0500
Bugzilla: 220238
Message-Id: <20070102220823.GL5381@redhat.com>
Changelog: x86: remove unwinder patches from x86/x86_64


bugzilla: 220238

The unwinder patches were dropped upstream, no need to support them in
RHEL-5 either.  

I tested the changes by running them through the normal kernel level
testing, the rhts kexec/kdump testing, and some manual panicing.  No ill
effects were noticed.  

The config changes:

#Index: configs/config-generic
#===================================================================
#RCS file: /cvs/dist/rpms/kernel/RHEL-5/configs/config-generic,v
#retrieving revision 1.262
#diff -u -r1.262 config-generic
#--- configs/config-generic	15 Dec 2006 23:48:13 -0000	1.262
#+++ configs/config-generic	2 Jan 2007 22:02:36 -0000
#@@ -2841,9 +2841,6 @@
 
 ## END of ISA options.
 
-CONFIG_UNWIND_INFO=y
-CONFIG_STACK_UNWIND=y
-
 # CONFIG_FORCED_INLINING is not set
 
 CONFIG_MIGRATION=y

The upstream stream changed (modified for RHEL-5) and the xen part:


Index: latest/Makefile
===================================================================
--- latest.orig/Makefile
+++ latest/Makefile
@@ -487,10 +487,6 @@ else
 CFLAGS		+= -fomit-frame-pointer
 endif
 
-ifdef CONFIG_UNWIND_INFO
-CFLAGS		+= -fasynchronous-unwind-tables
-endif
-
 ifdef CONFIG_DEBUG_INFO
 CFLAGS		+= -g
 endif
Index: latest/arch/i386/kernel/entry.S
===================================================================
--- latest.orig/arch/i386/kernel/entry.S
+++ latest/arch/i386/kernel/entry.S
@@ -927,37 +927,6 @@ ENTRY(spurious_interrupt_bug)
 	jmp error_code
 	CFI_ENDPROC
 
-#ifdef CONFIG_STACK_UNWIND
-ENTRY(arch_unwind_init_running)
-	CFI_STARTPROC
-	movl	4(%esp), %edx
-	movl	(%esp), %ecx
-	leal	4(%esp), %eax
-	movl	%ebx, EBX(%edx)
-	xorl	%ebx, %ebx
-	movl	%ebx, ECX(%edx)
-	movl	%ebx, EDX(%edx)
-	movl	%esi, ESI(%edx)
-	movl	%edi, EDI(%edx)
-	movl	%ebp, EBP(%edx)
-	movl	%ebx, EAX(%edx)
-	movl	$__USER_DS, DS(%edx)
-	movl	$__USER_DS, ES(%edx)
-	movl	%ebx, ORIG_EAX(%edx)
-	movl	%ecx, EIP(%edx)
-	movl	12(%esp), %ecx
-	movl	$__KERNEL_CS, CS(%edx)
-	movl	%ebx, EFLAGS(%edx)
-	movl	%eax, OLDESP(%edx)
-	movl	8(%esp), %eax
-	movl	%ecx, 8(%esp)
-	movl	EBX(%edx), %ebx
-	movl	$__KERNEL_DS, OLDSS(%edx)
-	jmpl	*%eax
-	CFI_ENDPROC
-ENDPROC(arch_unwind_init_running)
-#endif
-
 ENTRY(kernel_thread_helper)
 	pushl $0		# fake return address for unwinder
 	CFI_STARTPROC
Index: latest/arch/i386/kernel/traps.c
===================================================================
--- latest.orig/arch/i386/kernel/traps.c
+++ latest/arch/i386/kernel/traps.c
@@ -94,11 +94,6 @@ asmlinkage void spurious_interrupt_bug(v
 asmlinkage void machine_check(void);
 
 static int kstack_depth_to_print = 24;
-#ifdef CONFIG_STACK_UNWIND
-static int call_trace = 1;
-#else
-#define call_trace (-1)
-#endif
 ATOMIC_NOTIFIER_HEAD(i386die_chain);
 
 extern char last_sysfs_file[];
@@ -150,26 +145,6 @@ static inline unsigned long print_contex
 	return ebp;
 }
 
-struct ops_and_data {
-	struct stacktrace_ops *ops;
-	void *data;
-};
-
-static asmlinkage int
-dump_trace_unwind(struct unwind_frame_info *info, void *data)
-{
-	struct ops_and_data *oad = (struct ops_and_data *)data;
-	int n = 0;
-
-	while (unwind(info) == 0 && UNW_PC(info)) {
-		n++;
-		oad->ops->address(oad->data, UNW_PC(info));
-		if (arch_unw_user_mode(info))
-			break;
-	}
-	return n;
-}
-
 void dump_trace(struct task_struct *task, struct pt_regs *regs,
 	        unsigned long *stack,
 		struct stacktrace_ops *ops, void *data)
@@ -179,39 +154,6 @@ void dump_trace(struct task_struct *task
 	if (!task)
 		task = current;
 
-	if (call_trace >= 0) {
-		int unw_ret = 0;
-		struct unwind_frame_info info;
-		struct ops_and_data oad = { .ops = ops, .data = data };
-
-		if (regs) {
-			if (unwind_init_frame_info(&info, task, regs) == 0)
-				unw_ret = dump_trace_unwind(&info, &oad);
-		} else if (task == current)
-			unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad);
-		else {
-			if (unwind_init_blocked(&info, task) == 0)
-				unw_ret = dump_trace_unwind(&info, &oad);
-		}
-		if (unw_ret > 0) {
-			if (call_trace == 1 && !arch_unw_user_mode(&info)) {
-				ops->warning_symbol(data, "DWARF2 unwinder stuck at %s",
-					     UNW_PC(&info));
-				if (UNW_SP(&info) >= PAGE_OFFSET) {
-					ops->warning(data, "Leftover inexact backtrace:");
-					stack = (void *)UNW_SP(&info);
-					if (!stack)
-						return;
-					ebp = UNW_FP(&info);
-				} else
-					ops->warning(data, "Full inexact backtrace again:");
-			} else if (call_trace >= 1)
-				return;
-			else
-				ops->warning(data, "Full inexact backtrace again:");
-		} else
-			ops->warning(data, "Inexact backtrace:");
-	}
 	if (!stack) {
 		unsigned long dummy;
 		stack = &dummy;
@@ -1392,18 +1334,3 @@ static int __init kstack_setup(char *s)
 }
 __setup("kstack=", kstack_setup);
 
-#ifdef CONFIG_STACK_UNWIND
-static int __init call_trace_setup(char *s)
-{
-	if (strcmp(s, "old") == 0)
-		call_trace = -1;
-	else if (strcmp(s, "both") == 0)
-		call_trace = 0;
-	else if (strcmp(s, "newfallback") == 0)
-		call_trace = 1;
-	else if (strcmp(s, "new") == 2)
-		call_trace = 2;
-	return 1;
-}
-__setup("call_trace=", call_trace_setup);
-#endif
Index: latest/arch/x86_64/Makefile
===================================================================
--- latest.orig/arch/x86_64/Makefile
+++ latest/arch/x86_64/Makefile
@@ -45,9 +45,7 @@ cflags-kernel-$(CONFIG_REORDER) += -ffun
 # actually it makes the kernel smaller too.
 cflags-y += -fno-reorder-blocks
 cflags-y += -Wno-sign-compare
-ifneq ($(CONFIG_UNWIND_INFO),y)
 cflags-y += -fno-asynchronous-unwind-tables
-endif
 ifneq ($(CONFIG_DEBUG_INFO),y)
 # -fweb shrinks the kernel a bit, but the difference is very small
 # it also messes up debugging, so don't use it for now.
Index: latest/arch/x86_64/kernel/entry.S
===================================================================
--- latest.orig/arch/x86_64/kernel/entry.S
+++ latest/arch/x86_64/kernel/entry.S
@@ -1171,35 +1171,3 @@ ENTRY(call_softirq)
 	CFI_ENDPROC
 ENDPROC(call_softirq)
 
-#ifdef CONFIG_STACK_UNWIND
-ENTRY(arch_unwind_init_running)
-	CFI_STARTPROC
-	movq	%r15, R15(%rdi)
-	movq	%r14, R14(%rdi)
-	xchgq	%rsi, %rdx
-	movq	%r13, R13(%rdi)
-	movq	%r12, R12(%rdi)
-	xorl	%eax, %eax
-	movq	%rbp, RBP(%rdi)
-	movq	%rbx, RBX(%rdi)
-	movq	(%rsp), %rcx
-	movq	%rax, R11(%rdi)
-	movq	%rax, R10(%rdi)
-	movq	%rax, R9(%rdi)
-	movq	%rax, R8(%rdi)
-	movq	%rax, RAX(%rdi)
-	movq	%rax, RCX(%rdi)
-	movq	%rax, RDX(%rdi)
-	movq	%rax, RSI(%rdi)
-	movq	%rax, RDI(%rdi)
-	movq	%rax, ORIG_RAX(%rdi)
-	movq	%rcx, RIP(%rdi)
-	leaq	8(%rsp), %rcx
-	movq	$__KERNEL_CS, CS(%rdi)
-	movq	%rax, EFLAGS(%rdi)
-	movq	%rcx, RSP(%rdi)
-	movq	$__KERNEL_DS, SS(%rdi)
-	jmpq	*%rdx
-	CFI_ENDPROC
-ENDPROC(arch_unwind_init_running)
-#endif
Index: latest/arch/x86_64/kernel/traps.c
===================================================================
--- latest.orig/arch/x86_64/kernel/traps.c
+++ latest/arch/x86_64/kernel/traps.c
@@ -110,11 +110,6 @@ static inline void preempt_conditional_c
 }
 
 static int kstack_depth_to_print = 12;
-#ifdef CONFIG_STACK_UNWIND
-static int call_trace = 1;
-#else
-#define call_trace (-1)
-#endif
 
 #ifdef CONFIG_KALLSYMS
 # include <linux/kallsyms.h>
@@ -237,25 +232,6 @@ static unsigned long *in_exception_stack
 	return NULL;
 }
 
-struct ops_and_data {
-	struct stacktrace_ops *ops;
-	void *data;
-};
-
-static int dump_trace_unwind(struct unwind_frame_info *info, void *context)
-{
-	struct ops_and_data *oad = (struct ops_and_data *)context;
-	int n = 0;
-
-	while (unwind(info) == 0 && UNW_PC(info)) {
-		n++;
-		oad->ops->address(oad->data, UNW_PC(info));
-		if (arch_unw_user_mode(info))
-			break;
-	}
-	return n;
-}
-
 /*
  * x86-64 can have upto three kernel stacks: 
  * process stack
@@ -273,38 +249,6 @@ void dump_trace(struct task_struct *tsk,
 	if (!tsk)
 		tsk = current;
 
-	if (call_trace >= 0) {
-		int unw_ret = 0;
-		struct unwind_frame_info info;
-		struct ops_and_data oad = { .ops = ops, .data = data };
-
-		if (regs) {
-			if (unwind_init_frame_info(&info, tsk, regs) == 0)
-				unw_ret = dump_trace_unwind(&info, &oad);
-		} else if (tsk == current)
-			unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad);
-		else {
-			if (unwind_init_blocked(&info, tsk) == 0)
-				unw_ret = dump_trace_unwind(&info, &oad);
-		}
-		if (unw_ret > 0) {
-			if (call_trace == 1 && !arch_unw_user_mode(&info)) {
-				ops->warning_symbol(data, "DWARF2 unwinder stuck at %s",
-					     UNW_PC(&info));
-				if ((long)UNW_SP(&info) < 0) {
-					ops->warning(data, "Leftover inexact backtrace:");
-					stack = (unsigned long *)UNW_SP(&info);
-					if (!stack)
-						return;
-				} else
-					ops->warning(data, "Full inexact backtrace again:");
-			} else if (call_trace >= 1)
-				return;
-			else
-				ops->warning(data, "Full inexact backtrace again:");
-		} else
-			ops->warning(data, "Inexact backtrace:");
-	}
 	if (!stack) {
 		unsigned long dummy;
 		stack = &dummy;
@@ -1176,18 +1120,3 @@ static int __init kstack_setup(char *s)
 }
 __setup("kstack=", kstack_setup);
 
-#ifdef CONFIG_STACK_UNWIND
-static int __init call_trace_setup(char *s)
-{
-	if (strcmp(s, "old") == 0)
-		call_trace = -1;
-	else if (strcmp(s, "both") == 0)
-		call_trace = 0;
-	else if (strcmp(s, "newfallback") == 0)
-		call_trace = 1;
-	else if (strcmp(s, "new") == 0)
-		call_trace = 2;
-	return 1;
-}
-__setup("call_trace=", call_trace_setup);
-#endif
Index: latest/arch/x86_64/kernel/vmlinux.lds.S
===================================================================
--- latest.orig/arch/x86_64/kernel/vmlinux.lds.S
+++ latest/arch/x86_64/kernel/vmlinux.lds.S
@@ -239,9 +239,7 @@ SECTIONS
   /* Sections to be discarded */
   /DISCARD/ : {
 	*(.exitcall.exit)
-#ifndef CONFIG_UNWIND_INFO
 	*(.eh_frame)
-#endif
 	}
 
   STABS_DEBUG
Index: latest/include/asm-i386/unwind.h
===================================================================
--- latest.orig/include/asm-i386/unwind.h
+++ latest/include/asm-i386/unwind.h
@@ -1,93 +1,6 @@
 #ifndef _ASM_I386_UNWIND_H
 #define _ASM_I386_UNWIND_H
 
-/*
- * Copyright (C) 2002-2006 Novell, Inc.
- *	Jan Beulich <jbeulich@novell.com>
- * This code is released under version 2 of the GNU GPL.
- */
-
-#ifdef CONFIG_STACK_UNWIND
-
-#include <linux/sched.h>
-#include <asm/fixmap.h>
-#include <asm/ptrace.h>
-#include <asm/uaccess.h>
-
-struct unwind_frame_info
-{
-	struct pt_regs regs;
-	struct task_struct *task;
-};
-
-#define UNW_PC(frame)        (frame)->regs.eip
-#define UNW_SP(frame)        (frame)->regs.esp
-#ifdef CONFIG_FRAME_POINTER
-#define UNW_FP(frame)        (frame)->regs.ebp
-#define FRAME_RETADDR_OFFSET 4
-#define FRAME_LINK_OFFSET    0
-#define STACK_BOTTOM(tsk)    STACK_LIMIT((tsk)->thread.esp0)
-#define STACK_TOP(tsk)       ((tsk)->thread.esp0)
-#else
-#define UNW_FP(frame) ((void)(frame), 0)
-#endif
-#define STACK_LIMIT(ptr)     (((ptr) - 1) & ~(THREAD_SIZE - 1))
-
-#define UNW_REGISTER_INFO \
-	PTREGS_INFO(eax), \
-	PTREGS_INFO(ecx), \
-	PTREGS_INFO(edx), \
-	PTREGS_INFO(ebx), \
-	PTREGS_INFO(esp), \
-	PTREGS_INFO(ebp), \
-	PTREGS_INFO(esi), \
-	PTREGS_INFO(edi), \
-	PTREGS_INFO(eip)
-
-static inline void arch_unw_init_frame_info(struct unwind_frame_info *info,
-                                            /*const*/ struct pt_regs *regs)
-{
-	if (user_mode_vm(regs))
-		info->regs = *regs;
-	else {
-		memcpy(&info->regs, regs, offsetof(struct pt_regs, esp));
-		info->regs.esp = (unsigned long)&regs->esp;
-		info->regs.xss = __KERNEL_DS;
-	}
-}
-
-static inline void arch_unw_init_blocked(struct unwind_frame_info *info)
-{
-	memset(&info->regs, 0, sizeof(info->regs));
-	info->regs.eip = info->task->thread.eip;
-	info->regs.xcs = __KERNEL_CS;
-	__get_user(info->regs.ebp, (long *)info->task->thread.esp);
-	info->regs.esp = info->task->thread.esp;
-	info->regs.xss = __KERNEL_DS;
-	info->regs.xds = __USER_DS;
-	info->regs.xes = __USER_DS;
-}
-
-extern asmlinkage int arch_unwind_init_running(struct unwind_frame_info *,
-                                               asmlinkage int (*callback)(struct unwind_frame_info *,
-                                                                          void *arg),
-                                               void *arg);
-
-static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
-{
-#if 0 /* This can only work when selector register and EFLAGS saves/restores
-         are properly annotated (and tracked in UNW_REGISTER_INFO). */
-	return user_mode_vm(&info->regs);
-#else
-	return info->regs.eip < PAGE_OFFSET
-	       || (info->regs.eip >= __fix_to_virt(FIX_VDSO)
-	            && info->regs.eip < __fix_to_virt(FIX_VDSO) + PAGE_SIZE)
-	       || info->regs.esp < PAGE_OFFSET;
-#endif
-}
-
-#else
-
 #define UNW_PC(frame) ((void)(frame), 0)
 #define UNW_SP(frame) ((void)(frame), 0)
 #define UNW_FP(frame) ((void)(frame), 0)
@@ -97,6 +10,4 @@ static inline int arch_unw_user_mode(con
 	return 0;
 }
 
-#endif
-
 #endif /* _ASM_I386_UNWIND_H */
Index: latest/include/asm-x86_64/unwind.h
===================================================================
--- latest.orig/include/asm-x86_64/unwind.h
+++ latest/include/asm-x86_64/unwind.h
@@ -1,99 +1,6 @@
 #ifndef _ASM_X86_64_UNWIND_H
 #define _ASM_X86_64_UNWIND_H
 
-/*
- * Copyright (C) 2002-2006 Novell, Inc.
- *	Jan Beulich <jbeulich@novell.com>
- * This code is released under version 2 of the GNU GPL.
- */
-
-#ifdef CONFIG_STACK_UNWIND
-
-#include <linux/sched.h>
-#include <asm/ptrace.h>
-#include <asm/uaccess.h>
-#include <asm/vsyscall.h>
-
-struct unwind_frame_info
-{
-	struct pt_regs regs;
-	struct task_struct *task;
-};
-
-#define UNW_PC(frame)        (frame)->regs.rip
-#define UNW_SP(frame)        (frame)->regs.rsp
-#ifdef CONFIG_FRAME_POINTER
-#define UNW_FP(frame)        (frame)->regs.rbp
-#define FRAME_RETADDR_OFFSET 8
-#define FRAME_LINK_OFFSET    0
-#define STACK_BOTTOM(tsk)    (((tsk)->thread.rsp0 - 1) & ~(THREAD_SIZE - 1))
-#define STACK_TOP(tsk)       ((tsk)->thread.rsp0)
-#endif
-/* Might need to account for the special exception and interrupt handling
-   stacks here, since normally
-	EXCEPTION_STACK_ORDER < THREAD_ORDER < IRQSTACK_ORDER,
-   but the construct is needed only for getting across the stack switch to
-   the interrupt stack - thus considering the IRQ stack itself is unnecessary,
-   and the overhead of comparing against all exception handling stacks seems
-   not desirable. */
-#define STACK_LIMIT(ptr)     (((ptr) - 1) & ~(THREAD_SIZE - 1))
-
-#define UNW_REGISTER_INFO \
-	PTREGS_INFO(rax), \
-	PTREGS_INFO(rdx), \
-	PTREGS_INFO(rcx), \
-	PTREGS_INFO(rbx), \
-	PTREGS_INFO(rsi), \
-	PTREGS_INFO(rdi), \
-	PTREGS_INFO(rbp), \
-	PTREGS_INFO(rsp), \
-	PTREGS_INFO(r8), \
-	PTREGS_INFO(r9), \
-	PTREGS_INFO(r10), \
-	PTREGS_INFO(r11), \
-	PTREGS_INFO(r12), \
-	PTREGS_INFO(r13), \
-	PTREGS_INFO(r14), \
-	PTREGS_INFO(r15), \
-	PTREGS_INFO(rip)
-
-static inline void arch_unw_init_frame_info(struct unwind_frame_info *info,
-                                            /*const*/ struct pt_regs *regs)
-{
-	info->regs = *regs;
-}
-
-static inline void arch_unw_init_blocked(struct unwind_frame_info *info)
-{
-	extern const char thread_return[];
-
-	memset(&info->regs, 0, sizeof(info->regs));
-	info->regs.rip = (unsigned long)thread_return;
-	info->regs.cs = __KERNEL_CS;
-	__get_user(info->regs.rbp, (unsigned long *)info->task->thread.rsp);
-	info->regs.rsp = info->task->thread.rsp;
-	info->regs.ss = __KERNEL_DS;
-}
-
-extern int arch_unwind_init_running(struct unwind_frame_info *,
-                                    int (*callback)(struct unwind_frame_info *,
-                                                    void *arg),
-                                    void *arg);
-
-static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
-{
-#if 0 /* This can only work when selector register saves/restores
-         are properly annotated (and tracked in UNW_REGISTER_INFO). */
-	return user_mode(&info->regs);
-#else
-	return (long)info->regs.rip >= 0
-	       || (info->regs.rip >= VSYSCALL_START && info->regs.rip < VSYSCALL_END)
-	       || (long)info->regs.rsp >= 0;
-#endif
-}
-
-#else
-
 #define UNW_PC(frame) ((void)(frame), 0UL)
 #define UNW_SP(frame) ((void)(frame), 0UL)
 
@@ -102,6 +9,4 @@ static inline int arch_unw_user_mode(con
 	return 0;
 }
 
-#endif
-
 #endif /* _ASM_X86_64_UNWIND_H */
Index: latest/include/linux/unwind.h
===================================================================
--- latest.orig/include/linux/unwind.h
+++ latest/include/linux/unwind.h
@@ -14,62 +14,6 @@
 
 struct module;
 
-#ifdef CONFIG_STACK_UNWIND
-
-#include <asm/unwind.h>
-
-#ifndef ARCH_UNWIND_SECTION_NAME
-#define ARCH_UNWIND_SECTION_NAME ".eh_frame"
-#endif
-
-/*
- * Initialize unwind support.
- */
-extern void unwind_init(void);
-
-#ifdef CONFIG_MODULES
-
-extern void *unwind_add_table(struct module *,
-                              const void *table_start,
-                              unsigned long table_size);
-
-extern void unwind_remove_table(void *handle, int init_only);
-
-#endif
-
-extern int unwind_init_frame_info(struct unwind_frame_info *,
-                                  struct task_struct *,
-                                  /*const*/ struct pt_regs *);
-
-/*
- * Prepare to unwind a blocked task.
- */
-extern int unwind_init_blocked(struct unwind_frame_info *,
-                               struct task_struct *);
-
-/*
- * Prepare to unwind the currently running thread.
- */
-extern int unwind_init_running(struct unwind_frame_info *,
-                               asmlinkage int (*callback)(struct unwind_frame_info *,
-                                                          void *arg),
-                               void *arg);
-
-/*
- * Unwind to previous to frame.  Returns 0 if successful, negative
- * number in case of an error.
- */
-extern int unwind(struct unwind_frame_info *);
-
-/*
- * Unwind until the return pointer is in user-land (or until an error
- * occurs).  Returns 0 if successful, negative number in case of
- * error.
- */
-extern int unwind_to_user(struct unwind_frame_info *);
-
-#else
-
 struct unwind_frame_info {};
 
 static inline void unwind_init(void) {}
@@ -83,12 +27,12 @@ static inline void *unwind_add_table(str
 	return NULL;
 }
 
-#endif
-
 static inline void unwind_remove_table(void *handle, int init_only)
 {
 }
 
+#endif
+
 static inline int unwind_init_frame_info(struct unwind_frame_info *info,
                                          struct task_struct *tsk,
                                          const struct pt_regs *regs)
@@ -120,6 +64,4 @@ static inline int unwind_to_user(struct 
 	return -ENOSYS;
 }
 
-#endif
-
 #endif /* _LINUX_UNWIND_H */
Index: latest/kernel/Makefile
===================================================================
--- latest.orig/kernel/Makefile
+++ latest/kernel/Makefile
@@ -32,7 +32,6 @@ obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += module.o module-verify.o
 obj-$(CONFIG_MODULE_SIG) += module-verify-sig.o
 obj-$(CONFIG_KALLSYMS) += kallsyms.o
-obj-$(CONFIG_STACK_UNWIND) += unwind.o
 obj-$(CONFIG_PM) += power/
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
 obj-$(CONFIG_KEXEC) += kexec.o
Index: latest/kernel/unwind.c
===================================================================
--- latest.orig/kernel/unwind.c
+++ /dev/null
@@ -1,920 +0,0 @@
-/*
- * Copyright (C) 2002-2006 Novell, Inc.
- *	Jan Beulich <jbeulich@novell.com>
- * This code is released under version 2 of the GNU GPL.
- *
- * A simple API for unwinding kernel stacks.  This is used for
- * debugging and error reporting purposes.  The kernel doesn't need
- * full-blown stack unwinding with all the bells and whistles, so there
- * is not much point in implementing the full Dwarf2 unwind API.
- */
-
-#include <linux/unwind.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/stop_machine.h>
-#include <asm/sections.h>
-#include <asm/uaccess.h>
-#include <asm/unaligned.h>
-
-extern char __start_unwind[], __end_unwind[];
-
-#define MAX_STACK_DEPTH 8
-
-#define EXTRA_INFO(f) { \
-		BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \
-		                  % FIELD_SIZEOF(struct unwind_frame_info, f)) \
-		+ offsetof(struct unwind_frame_info, f) \
-		  / FIELD_SIZEOF(struct unwind_frame_info, f), \
-		FIELD_SIZEOF(struct unwind_frame_info, f) \
-	}
-#define PTREGS_INFO(f) EXTRA_INFO(regs.f)
-
-static const struct {
-	unsigned offs:BITS_PER_LONG / 2;
-	unsigned width:BITS_PER_LONG / 2;
-} reg_info[] = {
-	UNW_REGISTER_INFO
-};
-
-#undef PTREGS_INFO
-#undef EXTRA_INFO
-
-#ifndef REG_INVALID
-#define REG_INVALID(r) (reg_info[r].width == 0)
-#endif
-
-#define DW_CFA_nop                          0x00
-#define DW_CFA_set_loc                      0x01
-#define DW_CFA_advance_loc1                 0x02
-#define DW_CFA_advance_loc2                 0x03
-#define DW_CFA_advance_loc4                 0x04
-#define DW_CFA_offset_extended              0x05
-#define DW_CFA_restore_extended             0x06
-#define DW_CFA_undefined                    0x07
-#define DW_CFA_same_value                   0x08
-#define DW_CFA_register                     0x09
-#define DW_CFA_remember_state               0x0a
-#define DW_CFA_restore_state                0x0b
-#define DW_CFA_def_cfa                      0x0c
-#define DW_CFA_def_cfa_register             0x0d
-#define DW_CFA_def_cfa_offset               0x0e
-#define DW_CFA_def_cfa_expression           0x0f
-#define DW_CFA_expression                   0x10
-#define DW_CFA_offset_extended_sf           0x11
-#define DW_CFA_def_cfa_sf                   0x12
-#define DW_CFA_def_cfa_offset_sf            0x13
-#define DW_CFA_val_offset                   0x14
-#define DW_CFA_val_offset_sf                0x15
-#define DW_CFA_val_expression               0x16
-#define DW_CFA_lo_user                      0x1c
-#define DW_CFA_GNU_window_save              0x2d
-#define DW_CFA_GNU_args_size                0x2e
-#define DW_CFA_GNU_negative_offset_extended 0x2f
-#define DW_CFA_hi_user                      0x3f
-
-#define DW_EH_PE_FORM     0x07
-#define DW_EH_PE_native   0x00
-#define DW_EH_PE_leb128   0x01
-#define DW_EH_PE_data2    0x02
-#define DW_EH_PE_data4    0x03
-#define DW_EH_PE_data8    0x04
-#define DW_EH_PE_signed   0x08
-#define DW_EH_PE_ADJUST   0x70
-#define DW_EH_PE_abs      0x00
-#define DW_EH_PE_pcrel    0x10
-#define DW_EH_PE_textrel  0x20
-#define DW_EH_PE_datarel  0x30
-#define DW_EH_PE_funcrel  0x40
-#define DW_EH_PE_aligned  0x50
-#define DW_EH_PE_indirect 0x80
-#define DW_EH_PE_omit     0xff
-
-typedef unsigned long uleb128_t;
-typedef   signed long sleb128_t;
-
-static struct unwind_table {
-	struct {
-		unsigned long pc;
-		unsigned long range;
-	} core, init;
-	const void *address;
-	unsigned long size;
-	struct unwind_table *link;
-	const char *name;
-} root_table;
-
-struct unwind_item {
-	enum item_location {
-		Nowhere,
-		Memory,
-		Register,
-		Value
-	} where;
-	uleb128_t value;
-};
-
-struct unwind_state {
-	uleb128_t loc, org;
-	const u8 *cieStart, *cieEnd;
-	uleb128_t codeAlign;
-	sleb128_t dataAlign;
-	struct cfa {
-		uleb128_t reg, offs;
-	} cfa;
-	struct unwind_item regs[ARRAY_SIZE(reg_info)];
-	unsigned stackDepth:8;
-	unsigned version:8;
-	const u8 *label;
-	const u8 *stack[MAX_STACK_DEPTH];
-};
-
-static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };
-
-static struct unwind_table *find_table(unsigned long pc)
-{
-	struct unwind_table *table;
-
-	for (table = &root_table; table; table = table->link)
-		if ((pc >= table->core.pc
-		     && pc < table->core.pc + table->core.range)
-		    || (pc >= table->init.pc
-		        && pc < table->init.pc + table->init.range))
-			break;
-
-	return table;
-}
-
-static void init_unwind_table(struct unwind_table *table,
-                              const char *name,
-                              const void *core_start,
-                              unsigned long core_size,
-                              const void *init_start,
-                              unsigned long init_size,
-                              const void *table_start,
-                              unsigned long table_size)
-{
-	table->core.pc = (unsigned long)core_start;
-	table->core.range = core_size;
-	table->init.pc = (unsigned long)init_start;
-	table->init.range = init_size;
-	table->address = table_start;
-	table->size = table_size;
-	table->link = NULL;
-	table->name = name;
-}
-
-void __init unwind_init(void)
-{
-	init_unwind_table(&root_table, "kernel",
-	                  _text, _end - _text,
-	                  NULL, 0,
-	                  __start_unwind, __end_unwind - __start_unwind);
-}
-
-#ifdef CONFIG_MODULES
-
-static struct unwind_table *last_table;
-
-/* Must be called with module_mutex held. */
-void *unwind_add_table(struct module *module,
-                       const void *table_start,
-                       unsigned long table_size)
-{
-	struct unwind_table *table;
-
-	if (table_size <= 0)
-		return NULL;
-
-	table = kmalloc(sizeof(*table), GFP_KERNEL);
-	if (!table)
-		return NULL;
-
-	init_unwind_table(table, module->name,
-	                  module->module_core, module->core_size,
-	                  module->module_init, module->init_size,
-	                  table_start, table_size);
-
-	if (last_table)
-		last_table->link = table;
-	else
-		root_table.link = table;
-	last_table = table;
-
-	return table;
-}
-
-struct unlink_table_info
-{
-	struct unwind_table *table;
-	int init_only;
-};
-
-static int unlink_table(void *arg)
-{
-	struct unlink_table_info *info = arg;
-	struct unwind_table *table = info->table, *prev;
-
-	for (prev = &root_table; prev->link && prev->link != table; prev = prev->link)
-		;
-
-	if (prev->link) {
-		if (info->init_only) {
-			table->init.pc = 0;
-			table->init.range = 0;
-			info->table = NULL;
-		} else {
-			prev->link = table->link;
-			if (!prev->link)
-				last_table = prev;
-		}
-	} else
-		info->table = NULL;
-
-	return 0;
-}
-
-/* Must be called with module_mutex held. */
-void unwind_remove_table(void *handle, int init_only)
-{
-	struct unwind_table *table = handle;
-	struct unlink_table_info info;
-
-	if (!table || table == &root_table)
-		return;
-
-	if (init_only && table == last_table) {
-		table->init.pc = 0;
-		table->init.range = 0;
-		return;
-	}
-
-	info.table = table;
-	info.init_only = init_only;
-	stop_machine_run(unlink_table, &info, NR_CPUS);
-
-	if (info.table)
-		kfree(table);
-}
-
-#endif /* CONFIG_MODULES */
-
-static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
-{
-	const u8 *cur = *pcur;
-	uleb128_t value;
-	unsigned shift;
-
-	for (shift = 0, value = 0; cur < end; shift += 7) {
-		if (shift + 7 > 8 * sizeof(value)
-		    && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
-			cur = end + 1;
-			break;
-		}
-		value |= (uleb128_t)(*cur & 0x7f) << shift;
-		if (!(*cur++ & 0x80))
-			break;
-	}
-	*pcur = cur;
-
-	return value;
-}
-
-static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
-{
-	const u8 *cur = *pcur;
-	sleb128_t value;
-	unsigned shift;
-
-	for (shift = 0, value = 0; cur < end; shift += 7) {
-		if (shift + 7 > 8 * sizeof(value)
-		    && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
-			cur = end + 1;
-			break;
-		}
-		value |= (sleb128_t)(*cur & 0x7f) << shift;
-		if (!(*cur & 0x80)) {
-			value |= -(*cur++ & 0x40) << shift;
-			break;
-		}
-	}
-	*pcur = cur;
-
-	return value;
-}
-
-static unsigned long read_pointer(const u8 **pLoc,
-                                  const void *end,
-                                  signed ptrType)
-{
-	unsigned long value = 0;
-	union {
-		const u8 *p8;
-		const u16 *p16u;
-		const s16 *p16s;
-		const u32 *p32u;
-		const s32 *p32s;
-		const unsigned long *pul;
-	} ptr;
-
-	if (ptrType < 0 || ptrType == DW_EH_PE_omit)
-		return 0;
-	ptr.p8 = *pLoc;
-	switch(ptrType & DW_EH_PE_FORM) {
-	case DW_EH_PE_data2:
-		if (end < (const void *)(ptr.p16u + 1))
-			return 0;
-		if(ptrType & DW_EH_PE_signed)
-			value = get_unaligned(ptr.p16s++);
-		else
-			value = get_unaligned(ptr.p16u++);
-		break;
-	case DW_EH_PE_data4:
-#ifdef CONFIG_64BIT
-		if (end < (const void *)(ptr.p32u + 1))
-			return 0;
-		if(ptrType & DW_EH_PE_signed)
-			value = get_unaligned(ptr.p32s++);
-		else
-			value = get_unaligned(ptr.p32u++);
-		break;
-	case DW_EH_PE_data8:
-		BUILD_BUG_ON(sizeof(u64) != sizeof(value));
-#else
-		BUILD_BUG_ON(sizeof(u32) != sizeof(value));
-#endif
-	case DW_EH_PE_native:
-		if (end < (const void *)(ptr.pul + 1))
-			return 0;
-		value = get_unaligned(ptr.pul++);
-		break;
-	case DW_EH_PE_leb128:
-		BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
-		value = ptrType & DW_EH_PE_signed
-		        ? get_sleb128(&ptr.p8, end)
-		        : get_uleb128(&ptr.p8, end);
-		if ((const void *)ptr.p8 > end)
-			return 0;
-		break;
-	default:
-		return 0;
-	}
-	switch(ptrType & DW_EH_PE_ADJUST) {
-	case DW_EH_PE_abs:
-		break;
-	case DW_EH_PE_pcrel:
-		value += (unsigned long)*pLoc;
-		break;
-	default:
-		return 0;
-	}
-	if ((ptrType & DW_EH_PE_indirect)
-	    && __get_user(value, (unsigned long *)value))
-		return 0;
-	*pLoc = ptr.p8;
-
-	return value;
-}
-
-static signed fde_pointer_type(const u32 *cie)
-{
-	const u8 *ptr = (const u8 *)(cie + 2);
-	unsigned version = *ptr;
-
-	if (version != 1)
-		return -1; /* unsupported */
-	if (*++ptr) {
-		const char *aug;
-		const u8 *end = (const u8 *)(cie + 1) + *cie;
-		uleb128_t len;
-
-		/* check if augmentation size is first (and thus present) */
-		if (*ptr != 'z')
-			return -1;
-		/* check if augmentation string is nul-terminated */
-		if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL)
-			return -1;
-		++ptr; /* skip terminator */
-		get_uleb128(&ptr, end); /* skip code alignment */
-		get_sleb128(&ptr, end); /* skip data alignment */
-		/* skip return address column */
-		version <= 1 ? (void)++ptr : (void)get_uleb128(&ptr, end);
-		len = get_uleb128(&ptr, end); /* augmentation length */
-		if (ptr + len < ptr || ptr + len > end)
-			return -1;
-		end = ptr + len;
-		while (*++aug) {
-			if (ptr >= end)
-				return -1;
-			switch(*aug) {
-			case 'L':
-				++ptr;
-				break;
-			case 'P': {
-					signed ptrType = *ptr++;
-
-					if (!read_pointer(&ptr, end, ptrType) || ptr > end)
-						return -1;
-				}
-				break;
-			case 'R':
-				return *ptr;
-			default:
-				return -1;
-			}
-		}
-	}
-	return DW_EH_PE_native|DW_EH_PE_abs;
-}
-
-static int advance_loc(unsigned long delta, struct unwind_state *state)
-{
-	state->loc += delta * state->codeAlign;
-
-	return delta > 0;
-}
-
-static void set_rule(uleb128_t reg,
-                     enum item_location where,
-                     uleb128_t value,
-                     struct unwind_state *state)
-{
-	if (reg < ARRAY_SIZE(state->regs)) {
-		state->regs[reg].where = where;
-		state->regs[reg].value = value;
-	}
-}
-
-static int processCFI(const u8 *start,
-                      const u8 *end,
-                      unsigned long targetLoc,
-                      signed ptrType,
-                      struct unwind_state *state)
-{
-	union {
-		const u8 *p8;
-		const u16 *p16;
-		const u32 *p32;
-	} ptr;
-	int result = 1;
-
-	if (start != state->cieStart) {
-		state->loc = state->org;
-		result = processCFI(state->cieStart, state->cieEnd, 0, ptrType, state);
-		if (targetLoc == 0 && state->label == NULL)
-			return result;
-	}
-	for (ptr.p8 = start; result && ptr.p8 < end; ) {
-		switch(*ptr.p8 >> 6) {
-			uleb128_t value;
-
-		case 0:
-			switch(*ptr.p8++) {
-			case DW_CFA_nop:
-				break;
-			case DW_CFA_set_loc:
-				if ((state->loc = read_pointer(&ptr.p8, end, ptrType)) == 0)
-					result = 0;
-				break;
-			case DW_CFA_advance_loc1:
-				result = ptr.p8 < end && advance_loc(*ptr.p8++, state);
-				break;
-			case DW_CFA_advance_loc2:
-				result = ptr.p8 <= end + 2
-				         && advance_loc(*ptr.p16++, state);
-				break;
-			case DW_CFA_advance_loc4:
-				result = ptr.p8 <= end + 4
-				         && advance_loc(*ptr.p32++, state);
-				break;
-			case DW_CFA_offset_extended:
-				value = get_uleb128(&ptr.p8, end);
-				set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
-				break;
-			case DW_CFA_val_offset:
-				value = get_uleb128(&ptr.p8, end);
-				set_rule(value, Value, get_uleb128(&ptr.p8, end), state);
-				break;
-			case DW_CFA_offset_extended_sf:
-				value = get_uleb128(&ptr.p8, end);
-				set_rule(value, Memory, get_sleb128(&ptr.p8, end), state);
-				break;
-			case DW_CFA_val_offset_sf:
-				value = get_uleb128(&ptr.p8, end);
-				set_rule(value, Value, get_sleb128(&ptr.p8, end), state);
-				break;
-			case DW_CFA_restore_extended:
-			case DW_CFA_undefined:
-			case DW_CFA_same_value:
-				set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0, state);
-				break;
-			case DW_CFA_register:
-				value = get_uleb128(&ptr.p8, end);
-				set_rule(value,
-				         Register,
-				         get_uleb128(&ptr.p8, end), state);
-				break;
-			case DW_CFA_remember_state:
-				if (ptr.p8 == state->label) {
-					state->label = NULL;
-					return 1;
-				}
-				if (state->stackDepth >= MAX_STACK_DEPTH)
-					return 0;
-				state->stack[state->stackDepth++] = ptr.p8;
-				break;
-			case DW_CFA_restore_state:
-				if (state->stackDepth) {
-					const uleb128_t loc = state->loc;
-					const u8 *label = state->label;
-
-					state->label = state->stack[state->stackDepth - 1];
-					memcpy(&state->cfa, &badCFA, sizeof(state->cfa));
-					memset(state->regs, 0, sizeof(state->regs));
-					state->stackDepth = 0;
-					result = processCFI(start, end, 0, ptrType, state);
-					state->loc = loc;
-					state->label = label;
-				} else
-					return 0;
-				break;
-			case DW_CFA_def_cfa:
-				state->cfa.reg = get_uleb128(&ptr.p8, end);
-				/*nobreak*/
-			case DW_CFA_def_cfa_offset:
-				state->cfa.offs = get_uleb128(&ptr.p8, end);
-				break;
-			case DW_CFA_def_cfa_sf:
-				state->cfa.reg = get_uleb128(&ptr.p8, end);
-				/*nobreak*/
-			case DW_CFA_def_cfa_offset_sf:
-				state->cfa.offs = get_sleb128(&ptr.p8, end)
-				                  * state->dataAlign;
-				break;
-			case DW_CFA_def_cfa_register:
-				state->cfa.reg = get_uleb128(&ptr.p8, end);
-				break;
-			/*todo case DW_CFA_def_cfa_expression: */
-			/*todo case DW_CFA_expression: */
-			/*todo case DW_CFA_val_expression: */
-			case DW_CFA_GNU_args_size:
-				get_uleb128(&ptr.p8, end);
-				break;
-			case DW_CFA_GNU_negative_offset_extended:
-				value = get_uleb128(&ptr.p8, end);
-				set_rule(value,
-				         Memory,
-				         (uleb128_t)0 - get_uleb128(&ptr.p8, end), state);
-				break;
-			case DW_CFA_GNU_window_save:
-			default:
-				result = 0;
-				break;
-			}
-			break;
-		case 1:
-			result = advance_loc(*ptr.p8++ & 0x3f, state);
-			break;
-		case 2:
-			value = *ptr.p8++ & 0x3f;
-			set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
-			break;
-		case 3:
-			set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
-			break;
-		}
-		if (ptr.p8 > end)
-			result = 0;
-		if (result && targetLoc != 0 && targetLoc < state->loc)
-			return 1;
-	}
-
-	return result
-	   && ptr.p8 == end
-	   && (targetLoc == 0
-	    || (/*todo While in theory this should apply, gcc in practice omits
-	          everything past the function prolog, and hence the location
-	          never reaches the end of the function.
-	        targetLoc < state->loc &&*/ state->label == NULL));
-}
-
-/* Unwind to previous to frame.  Returns 0 if successful, negative
- * number in case of an error. */
-int unwind(struct unwind_frame_info *frame)
-{
-#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
-	const u32 *fde = NULL, *cie = NULL;
-	const u8 *ptr = NULL, *end = NULL;
-	unsigned long startLoc = 0, endLoc = 0, cfa;
-	unsigned i;
-	signed ptrType = -1;
-	uleb128_t retAddrReg = 0;
-	struct unwind_table *table;
-	struct unwind_state state;
-
-	if (UNW_PC(frame) == 0)
-		return -EINVAL;
-	if ((table = find_table(UNW_PC(frame))) != NULL
-	    && !(table->size & (sizeof(*fde) - 1))) {
-		unsigned long tableSize = table->size;
-
-		for (fde = table->address;
-		     tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
-		     tableSize -= sizeof(*fde) + *fde,
-		     fde += 1 + *fde / sizeof(*fde)) {
-			if (!*fde || (*fde & (sizeof(*fde) - 1)))
-				break;
-			if (!fde[1])
-				continue; /* this is a CIE */
-			if ((fde[1] & (sizeof(*fde) - 1))
-			    || fde[1] > (unsigned long)(fde + 1)
-			                - (unsigned long)table->address)
-				continue; /* this is not a valid FDE */
-			cie = fde + 1 - fde[1] / sizeof(*fde);
-			if (*cie <= sizeof(*cie) + 4
-			    || *cie >= fde[1] - sizeof(*fde)
-			    || (*cie & (sizeof(*cie) - 1))
-			    || cie[1]
-			    || (ptrType = fde_pointer_type(cie)) < 0) {
-				cie = NULL; /* this is not a (valid) CIE */
-				continue;
-			}
-			ptr = (const u8 *)(fde + 2);
-			startLoc = read_pointer(&ptr,
-			                        (const u8 *)(fde + 1) + *fde,
-			                        ptrType);
-			endLoc = startLoc
-			         + read_pointer(&ptr,
-			                        (const u8 *)(fde + 1) + *fde,
-			                        ptrType & DW_EH_PE_indirect
-			                        ? ptrType
-			                        : ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed));
-			if (UNW_PC(frame) >= startLoc && UNW_PC(frame) < endLoc)
-				break;
-			cie = NULL;
-		}
-	}
-	if (cie != NULL) {
-		memset(&state, 0, sizeof(state));
-		state.cieEnd = ptr; /* keep here temporarily */
-		ptr = (const u8 *)(cie + 2);
-		end = (const u8 *)(cie + 1) + *cie;
-		if ((state.version = *ptr) != 1)
-			cie = NULL; /* unsupported version */
-		else if (*++ptr) {
-			/* check if augmentation size is first (and thus present) */
-			if (*ptr == 'z') {
-				/* check for ignorable (or already handled)
-				 * nul-terminated augmentation string */
-				while (++ptr < end && *ptr)
-					if (strchr("LPR", *ptr) == NULL)
-						break;
-			}
-			if (ptr >= end || *ptr)
-				cie = NULL;
-		}
-		++ptr;
-	}
-	if (cie != NULL) {
-		/* get code aligment factor */
-		state.codeAlign = get_uleb128(&ptr, end);
-		/* get data aligment factor */
-		state.dataAlign = get_sleb128(&ptr, end);
-		if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
-			cie = NULL;
-		else {
-			retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end);
-			/* skip augmentation */
-			if (((const char *)(cie + 2))[1] == 'z')
-				ptr += get_uleb128(&ptr, end);
-			if (ptr > end
-			   || retAddrReg >= ARRAY_SIZE(reg_info)
-			   || REG_INVALID(retAddrReg)
-			   || reg_info[retAddrReg].width != sizeof(unsigned long))
-				cie = NULL;
-		}
-	}
-	if (cie != NULL) {
-		state.cieStart = ptr;
-		ptr = state.cieEnd;
-		state.cieEnd = end;
-		end = (const u8 *)(fde + 1) + *fde;
-		/* skip augmentation */
-		if (((const char *)(cie + 2))[1] == 'z') {
-			uleb128_t augSize = get_uleb128(&ptr, end);
-
-			if ((ptr += augSize) > end)
-				fde = NULL;
-		}
-	}
-	if (cie == NULL || fde == NULL) {
-#ifdef CONFIG_FRAME_POINTER
-		unsigned long top, bottom;
-#endif
-
-#ifdef CONFIG_FRAME_POINTER
-		top = STACK_TOP(frame->task);
-		bottom = STACK_BOTTOM(frame->task);
-# if FRAME_RETADDR_OFFSET < 0
-		if (UNW_SP(frame) < top
-		    && UNW_FP(frame) <= UNW_SP(frame)
-		    && bottom < UNW_FP(frame)
-# else
-		if (UNW_SP(frame) > top
-		    && UNW_FP(frame) >= UNW_SP(frame)
-		    && bottom > UNW_FP(frame)
-# endif
-		   && !((UNW_SP(frame) | UNW_FP(frame))
-		        & (sizeof(unsigned long) - 1))) {
-			unsigned long link;
-
-			if (!__get_user(link,
-			                (unsigned long *)(UNW_FP(frame)
-			                                  + FRAME_LINK_OFFSET))
-# if FRAME_RETADDR_OFFSET < 0
-			   && link > bottom && link < UNW_FP(frame)
-# else
-			   && link > UNW_FP(frame) && link < bottom
-# endif
-			   && !(link & (sizeof(link) - 1))
-			   && !__get_user(UNW_PC(frame),
-			                  (unsigned long *)(UNW_FP(frame)
-			                                    + FRAME_RETADDR_OFFSET))) {
-				UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET
-# if FRAME_RETADDR_OFFSET < 0
-					-
-# else
-					+
-# endif
-					  sizeof(UNW_PC(frame));
-				UNW_FP(frame) = link;
-				return 0;
-			}
-		}
-#endif
-		return -ENXIO;
-	}
-	state.org = startLoc;
-	memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
-	/* process instructions */
-	if (!processCFI(ptr, end, UNW_PC(frame), ptrType, &state)
-	   || state.loc > endLoc
-	   || state.regs[retAddrReg].where == Nowhere
-	   || state.cfa.reg >= ARRAY_SIZE(reg_info)
-	   || reg_info[state.cfa.reg].width != sizeof(unsigned long)
-	   || state.cfa.offs % sizeof(unsigned long))
-		return -EIO;
-	/* update frame */
-	cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
-	startLoc = min((unsigned long)UNW_SP(frame), cfa);
-	endLoc = max((unsigned long)UNW_SP(frame), cfa);
-	if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
-		startLoc = min(STACK_LIMIT(cfa), cfa);
-		endLoc = max(STACK_LIMIT(cfa), cfa);
-	}
-#ifndef CONFIG_64BIT
-# define CASES CASE(8); CASE(16); CASE(32)
-#else
-# define CASES CASE(8); CASE(16); CASE(32); CASE(64)
-#endif
-	for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
-		if (REG_INVALID(i)) {
-			if (state.regs[i].where == Nowhere)
-				continue;
-			return -EIO;
-		}
-		switch(state.regs[i].where) {
-		default:
-			break;
-		case Register:
-			if (state.regs[i].value >= ARRAY_SIZE(reg_info)
-			   || REG_INVALID(state.regs[i].value)
-			   || reg_info[i].width > reg_info[state.regs[i].value].width)
-				return -EIO;
-			switch(reg_info[state.regs[i].value].width) {
-#define CASE(n) \
-			case sizeof(u##n): \
-				state.regs[i].value = FRAME_REG(state.regs[i].value, \
-				                                const u##n); \
-				break
-			CASES;
-#undef CASE
-			default:
-				return -EIO;
-			}
-			break;
-		}
-	}
-	for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
-		if (REG_INVALID(i))
-			continue;
-		switch(state.regs[i].where) {
-		case Nowhere:
-			if (reg_info[i].width != sizeof(UNW_SP(frame))
-			   || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
-			      != &UNW_SP(frame))
-				continue;
-			UNW_SP(frame) = cfa;
-			break;
-		case Register:
-			switch(reg_info[i].width) {
-#define CASE(n) case sizeof(u##n): \
-				FRAME_REG(i, u##n) = state.regs[i].value; \
-				break
-			CASES;
-#undef CASE
-			default:
-				return -EIO;
-			}
-			break;
-		case Value:
-			if (reg_info[i].width != sizeof(unsigned long))
-				return -EIO;
-			FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
-			                                    * state.dataAlign;
-			break;
-		case Memory: {
-				unsigned long addr = cfa + state.regs[i].value
-				                           * state.dataAlign;
-
-				if ((state.regs[i].value * state.dataAlign)
-				    % sizeof(unsigned long)
-				    || addr < startLoc
-				    || addr + sizeof(unsigned long) < addr
-				    || addr + sizeof(unsigned long) > endLoc)
-					return -EIO;
-				switch(reg_info[i].width) {
-#define CASE(n)     case sizeof(u##n): \
-					__get_user(FRAME_REG(i, u##n), (u##n *)addr); \
-					break
-				CASES;
-#undef CASE
-				default:
-					return -EIO;
-				}
-			}
-			break;
-		}
-	}
-
-	return 0;
-#undef CASES
-#undef FRAME_REG
-}
-EXPORT_SYMBOL(unwind);
-
-int unwind_init_frame_info(struct unwind_frame_info *info,
-                           struct task_struct *tsk,
-                           /*const*/ struct pt_regs *regs)
-{
-	info->task = tsk;
-	arch_unw_init_frame_info(info, regs);
-
-	return 0;
-}
-EXPORT_SYMBOL(unwind_init_frame_info);
-
-/*
- * Prepare to unwind a blocked task.
- */
-int unwind_init_blocked(struct unwind_frame_info *info,
-                        struct task_struct *tsk)
-{
-	info->task = tsk;
-	arch_unw_init_blocked(info);
-
-	return 0;
-}
-EXPORT_SYMBOL(unwind_init_blocked);
-
-/*
- * Prepare to unwind the currently running thread.
- */
-int unwind_init_running(struct unwind_frame_info *info,
-                        asmlinkage int (*callback)(struct unwind_frame_info *,
-                                                   void *arg),
-                        void *arg)
-{
-	info->task = current;
-
-	return arch_unwind_init_running(info, callback, arg);
-}
-EXPORT_SYMBOL(unwind_init_running);
-
-/*
- * Unwind until the return pointer is in user-land (or until an error
- * occurs).  Returns 0 if successful, negative number in case of
- * error.
- */
-int unwind_to_user(struct unwind_frame_info *info)
-{
-	while (!arch_unw_user_mode(info)) {
-		int err = unwind(info);
-
-		if (err < 0)
-			return err;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(unwind_to_user);
Index: latest/lib/Kconfig.debug
===================================================================
--- latest.orig/lib/Kconfig.debug
+++ latest/lib/Kconfig.debug
@@ -332,24 +332,6 @@ config FRAME_POINTER
 	  some architectures or if you use external debuggers.
 	  If you don't debug the kernel, you can say N.
 
-config UNWIND_INFO
-	bool "Compile the kernel with frame unwind information"
-	depends on !IA64 && !PARISC && !X86_64_XEN
-	depends on !MODULES || !(MIPS || PPC || SUPERH || V850)
-	help
-	  If you say Y here the resulting kernel image will be slightly larger
-	  but not slower, and it will give very useful debugging information.
-	  If you don't debug the kernel, you can say N, but we may not be able
-	  to solve problems without frame unwind information or frame pointers.
-
-config STACK_UNWIND
-	bool "Stack unwind support"
-	depends on UNWIND_INFO
-	depends on X86
-	help
-	  This enables more precise stack traces, omitting all unrelated
-	  occurrences of pointers into kernel code from the dump.
-
 config FORCED_INLINING
 	bool "Force gcc to inline functions marked 'inline'"
 	depends on DEBUG_KERNEL

From: Don Zickus <dzickus@redhat.com>
Subject: [RHEL-5 PATCH 2/2] remove unwinder patches from x86/x86_64
Date: Tue, 2 Jan 2007 17:09:47 -0500
Bugzilla: NONE
Message-Id: <20070102220947.GM5381@redhat.com>


The xen part of the stack unwinder removal.


Index: latest/arch/i386/kernel/entry-xen.S
===================================================================
--- latest.orig/arch/i386/kernel/entry-xen.S
+++ latest/arch/i386/kernel/entry-xen.S
@@ -1173,37 +1173,6 @@ ENTRY(fixup_4gb_segment)
 	jmp error_code
 	CFI_ENDPROC
 
-#ifdef CONFIG_STACK_UNWIND
-ENTRY(arch_unwind_init_running)
-	CFI_STARTPROC
-	movl	4(%esp), %edx
-	movl	(%esp), %ecx
-	leal	4(%esp), %eax
-	movl	%ebx, EBX(%edx)
-	xorl	%ebx, %ebx
-	movl	%ebx, ECX(%edx)
-	movl	%ebx, EDX(%edx)
-	movl	%esi, ESI(%edx)
-	movl	%edi, EDI(%edx)
-	movl	%ebp, EBP(%edx)
-	movl	%ebx, EAX(%edx)
-	movl	$__USER_DS, DS(%edx)
-	movl	$__USER_DS, ES(%edx)
-	movl	%ebx, ORIG_EAX(%edx)
-	movl	%ecx, EIP(%edx)
-	movl	12(%esp), %ecx
-	movl	$__KERNEL_CS, CS(%edx)
-	movl	%ebx, EFLAGS(%edx)
-	movl	%eax, OLDESP(%edx)
-	movl	8(%esp), %eax
-	movl	%ecx, 8(%esp)
-	movl	EBX(%edx), %ebx
-	movl	$__KERNEL_DS, OLDSS(%edx)
-	jmpl	*%eax
-	CFI_ENDPROC
-ENDPROC(arch_unwind_init_running)
-#endif
-
 .section .rodata,"a"
 #include "syscall_table.S"
 
Index: latest/arch/i386/kernel/traps-xen.c
===================================================================
--- latest.orig/arch/i386/kernel/traps-xen.c
+++ latest/arch/i386/kernel/traps-xen.c
@@ -100,11 +100,6 @@ asmlinkage void fixup_4gb_segment(void);
 asmlinkage void machine_check(void);
 
 static int kstack_depth_to_print = 24;
-#ifdef CONFIG_STACK_UNWIND
-static int call_trace = 1;
-#else
-#define call_trace (-1)
-#endif
 ATOMIC_NOTIFIER_HEAD(i386die_chain);
 
 extern char last_sysfs_file[];
@@ -156,26 +151,6 @@ static inline unsigned long print_contex
 	return ebp;
 }
 
-struct ops_and_data {
-	struct stacktrace_ops *ops;
-	void *data;
-};
-
-static asmlinkage int
-dump_trace_unwind(struct unwind_frame_info *info, void *data)
-{
-	struct ops_and_data *oad = (struct ops_and_data *)data;
-	int n = 0;
-
-	while (unwind(info) == 0 && UNW_PC(info)) {
-		n++;
-		oad->ops->address(oad->data, UNW_PC(info));
-		if (arch_unw_user_mode(info))
-			break;
-	}
-	return n;
-}
-
 void dump_trace(struct task_struct *task, struct pt_regs *regs,
 	unsigned long *stack,
 	struct stacktrace_ops *ops, void *data)
@@ -185,37 +160,7 @@ void dump_trace(struct task_struct *task
 	if (!task)
 		task = current;
 
-	if (call_trace >= 0) {
-		int unw_ret = 0;
-		struct unwind_frame_info info;
-		struct ops_and_data oad = { .ops = ops, .data = data };
-
-		if (regs) {
-			if (unwind_init_frame_info(&info, task, regs) == 0)
-				unw_ret = dump_trace_unwind(&info, &oad);
-		} else if (task == current)
-			unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad);
-		else {
-			if (unwind_init_blocked(&info, task) == 0)
-				unw_ret = dump_trace_unwind(&info, &oad);
-		}
-		if (unw_ret > 0) {
-			if (call_trace == 1 && !arch_unw_user_mode(&info)) {
-				ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n",
-					     UNW_PC(&info));
-				if (UNW_SP(&info) >= PAGE_OFFSET) {
-					ops->warning(data, "Leftover inexact backtrace:\n");
-					stack = (void *)UNW_SP(&info);
-				} else
-					ops->warning(data, "Full inexact backtrace again:\n");
-			} else if (call_trace >= 1)
-				return;
-			else
-				ops->warning(data, "Full inexact backtrace again:\n");
-		} else
-			ops->warning(data, "Inexact backtrace:\n");
-
-	} else if (!stack) {
+	if (!stack) {
 		unsigned long dummy;
 		stack = &dummy;
 		if (task && task != current)
@@ -1321,18 +1266,3 @@ static int __init kstack_setup(char *s)
 }
 __setup("kstack=", kstack_setup);
 
-#ifdef CONFIG_STACK_UNWIND
-static int __init call_trace_setup(char *s)
-{
-	if (strcmp(s, "old") == 0)
-		call_trace = -1;
-	else if (strcmp(s, "both") == 0)
-		call_trace = 0;
-	else if (strcmp(s, "newfallback") == 0)
-		call_trace = 1;
-	else if (strcmp(s, "new") == 2)
-		call_trace = 2;
-	return 1;
-}
-__setup("call_trace=", call_trace_setup);
-#endif
Index: latest/arch/x86_64/kernel/entry-xen.S
===================================================================
--- latest.orig/arch/x86_64/kernel/entry-xen.S
+++ latest/arch/x86_64/kernel/entry-xen.S
@@ -1179,35 +1179,3 @@ ENTRY(call_softirq)
 	CFI_ENDPROC
 ENDPROC(call_softirq)
 
-#ifdef CONFIG_STACK_UNWIND
-ENTRY(arch_unwind_init_running)
-	CFI_STARTPROC
-	movq	%r15, R15(%rdi)
-	movq	%r14, R14(%rdi)
-	xchgq	%rsi, %rdx
-	movq	%r13, R13(%rdi)
-	movq	%r12, R12(%rdi)
-	xorl	%eax, %eax
-	movq	%rbp, RBP(%rdi)
-	movq	%rbx, RBX(%rdi)
-	movq	(%rsp), %rcx
-	movq	%rax, R11(%rdi)
-	movq	%rax, R10(%rdi)
-	movq	%rax, R9(%rdi)
-	movq	%rax, R8(%rdi)
-	movq	%rax, RAX(%rdi)
-	movq	%rax, RCX(%rdi)
-	movq	%rax, RDX(%rdi)
-	movq	%rax, RSI(%rdi)
-	movq	%rax, RDI(%rdi)
-	movq	%rax, ORIG_RAX(%rdi)
-	movq	%rcx, RIP(%rdi)
-	leaq	8(%rsp), %rcx
-	movq	$__KERNEL_CS, CS(%rdi)
-	movq	%rax, EFLAGS(%rdi)
-	movq	%rcx, RSP(%rdi)
-	movq	$__KERNEL_DS, SS(%rdi)
-	jmpq	*%rdx
-	CFI_ENDPROC
-ENDPROC(arch_unwind_init_running)
-#endif
Index: latest/arch/x86_64/kernel/traps-xen.c
===================================================================
--- latest.orig/arch/x86_64/kernel/traps-xen.c
+++ latest/arch/x86_64/kernel/traps-xen.c
@@ -109,12 +109,6 @@ static inline void preempt_conditional_c
 }
 
 static int kstack_depth_to_print = 10;
-#ifdef CONFIG_STACK_UNWIND
-static int call_trace = 1;
-#else
-#define call_trace (-1)
-#endif
-
 
 #ifdef CONFIG_KALLSYMS
 # include <linux/kallsyms.h>
@@ -239,25 +233,6 @@ static unsigned long *in_exception_stack
 	return NULL;
 }
 
-struct ops_and_data {
-	struct stacktrace_ops *ops;
-	void *data;
-};
-
-static int dump_trace_unwind(struct unwind_frame_info *info, void *context)
-{
-	struct ops_and_data *oad = (struct ops_and_data *)context;
-	int n = 0;
-
-	while (unwind(info) == 0 && UNW_PC(info)) {
-		if (arch_unw_user_mode(info))
-			break;
-		n++;
-		oad->ops->address(oad->data, UNW_PC(info));
-	}
-	return n;
-}
-
 /*
  * x86-64 can have upto three kernel stacks: 
  * process stack
@@ -275,36 +250,6 @@ void dump_trace(struct task_struct *tsk,
 	if (!tsk)
 		tsk = current;
 
-	if (call_trace >= 0) {
-		int unw_ret = 0;
-		struct unwind_frame_info info;
-		struct ops_and_data oad = { .ops = ops, .data = data };
-
-		if (regs) {
-			if (unwind_init_frame_info(&info, tsk, regs) == 0)
-				unw_ret = dump_trace_unwind(&info, &oad);
-		} else if (tsk == current)
-			unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad);
-		else {
-			if (unwind_init_blocked(&info, tsk) == 0)
-				unw_ret = dump_trace_unwind(&info, &oad);
-		}
-		if (unw_ret > 0) {
-			if (call_trace == 1 && !arch_unw_user_mode(&info)) {
-				ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n",
-					     UNW_PC(&info));
-				if ((long)UNW_SP(&info) < 0) {
-					ops->warning(data, "Leftover inexact backtrace:\n");
-					stack = (unsigned long *)UNW_SP(&info);
-				} else
-					ops->warning(data, "Full inexact backtrace again:\n");
-			} else if (call_trace >= 1)
-				return;
-			else
-				ops->warning(data, "Full inexact backtrace again:\n");
-		} else
-			ops->warning(data, "Inexact backtrace:\n");
-	}
 	if (!stack) {
 		unsigned long dummy;
 		stack = &dummy;
@@ -1207,18 +1152,3 @@ static int __init kstack_setup(char *s)
 }
 __setup("kstack=", kstack_setup);
 
-#ifdef CONFIG_STACK_UNWIND
-static int __init call_trace_setup(char *s)
-{
-	if (strcmp(s, "old") == 0)
-		call_trace = -1;
-	else if (strcmp(s, "both") == 0)
-		call_trace = 0;
-	else if (strcmp(s, "newfallback") == 0)
-		call_trace = 1;
- 	else if (strcmp(s, "new") == 0)
-		call_trace = 2;
-	return 1;
-}
-__setup("call_trace=", call_trace_setup);
-#endif