]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.31/patches.xen/xen3-stack-unwind
Add a patch to fix Intel E100 wake-on-lan problems.
[ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.xen / xen3-stack-unwind
CommitLineData
2cb7cef9
BS
1Subject: DWARF2 EH-frame based stack unwinding
2From: jbeulich@novell.com
3Patch-mainline: no
4
5Automatically created from "patches.suse/stack-unwind" by xen-port-patches.py
6
7--- sle11-2009-05-14.orig/arch/x86/kernel/entry_32-xen.S 2009-05-14 11:20:49.000000000 +0200
8+++ sle11-2009-05-14/arch/x86/kernel/entry_32-xen.S 2009-05-14 11:29:34.000000000 +0200
9@@ -1290,6 +1290,38 @@ ENTRY(fixup_4gb_segment)
10 CFI_ENDPROC
11 END(spurious_interrupt_bug)
12
13+#ifdef CONFIG_STACK_UNWIND
14+ENTRY(arch_unwind_init_running)
15+ CFI_STARTPROC
16+ movl 4(%esp), %edx
17+ movl (%esp), %ecx
18+ leal 4(%esp), %eax
19+ movl %ebx, PT_EBX(%edx)
20+ xorl %ebx, %ebx
21+ movl %ebx, PT_ECX(%edx)
22+ movl %ebx, PT_EDX(%edx)
23+ movl %esi, PT_ESI(%edx)
24+ movl %edi, PT_EDI(%edx)
25+ movl %ebp, PT_EBP(%edx)
26+ movl %ebx, PT_EAX(%edx)
27+ movl $__USER_DS, PT_DS(%edx)
28+ movl $__USER_DS, PT_ES(%edx)
29+ movl $__KERNEL_PERCPU, PT_FS(%edx)
30+ movl %ebx, PT_ORIG_EAX(%edx)
31+ movl %ecx, PT_EIP(%edx)
32+ movl 12(%esp), %ecx
33+ movl $__KERNEL_CS, PT_CS(%edx)
34+ movl %ebx, PT_EFLAGS(%edx)
35+ movl %eax, PT_OLDESP(%edx)
36+ movl 8(%esp), %eax
37+ movl %ecx, 8(%esp)
38+ movl PT_EBX(%edx), %ebx
39+ movl $__KERNEL_DS, PT_OLDSS(%edx)
40+ jmpl *%eax
41+ CFI_ENDPROC
42+ENDPROC(arch_unwind_init_running)
43+#endif
44+
45 ENTRY(kernel_thread_helper)
46 pushl $0 # fake return address for unwinder
47 CFI_STARTPROC
48--- sle11-2009-05-14.orig/arch/x86/kernel/entry_64-xen.S 2009-03-16 16:38:16.000000000 +0100
49+++ sle11-2009-05-14/arch/x86/kernel/entry_64-xen.S 2008-11-25 13:17:09.000000000 +0100
50@@ -1419,3 +1419,36 @@ KPROBE_ENTRY(ignore_sysret)
51 HYPERVISOR_IRET 0
52 CFI_ENDPROC
53 ENDPROC(ignore_sysret)
54+
55+#ifdef CONFIG_STACK_UNWIND
56+ENTRY(arch_unwind_init_running)
57+ CFI_STARTPROC
58+ movq %r15, R15(%rdi)
59+ movq %r14, R14(%rdi)
60+ xchgq %rsi, %rdx
61+ movq %r13, R13(%rdi)
62+ movq %r12, R12(%rdi)
63+ xorl %eax, %eax
64+ movq %rbp, RBP(%rdi)
65+ movq %rbx, RBX(%rdi)
66+ movq (%rsp), %rcx
67+ movq %rax, R11(%rdi)
68+ movq %rax, R10(%rdi)
69+ movq %rax, R9(%rdi)
70+ movq %rax, R8(%rdi)
71+ movq %rax, RAX(%rdi)
72+ movq %rax, RCX(%rdi)
73+ movq %rax, RDX(%rdi)
74+ movq %rax, RSI(%rdi)
75+ movq %rax, RDI(%rdi)
76+ movq %rax, ORIG_RAX(%rdi)
77+ movq %rcx, RIP(%rdi)
78+ leaq 8(%rsp), %rcx
79+ movq $__KERNEL_CS, CS(%rdi)
80+ movq %rax, EFLAGS(%rdi)
81+ movq %rcx, RSP(%rdi)
82+ movq $__KERNEL_DS, SS(%rdi)
83+ jmpq *%rdx
84+ CFI_ENDPROC
85+ENDPROC(arch_unwind_init_running)
86+#endif
87--- sle11-2009-05-14.orig/arch/x86/kernel/traps_32-xen.c 2008-11-25 13:17:06.000000000 +0100
88+++ sle11-2009-05-14/arch/x86/kernel/traps_32-xen.c 2008-11-25 13:17:09.000000000 +0100
89@@ -86,6 +86,11 @@ int panic_on_unrecovered_nmi;
90 int panic_on_io_nmi;
91 int kstack_depth_to_print = 24;
92 static unsigned int code_bytes = 64;
93+#ifdef CONFIG_STACK_UNWIND
94+static int call_trace = 1;
95+#else
96+#define call_trace (-1)
97+#endif
98 static int ignore_nmis;
99 static int die_counter;
100
101@@ -156,6 +161,33 @@ print_context_stack(struct thread_info *
102 return bp;
103 }
104
105+struct ops_and_data {
106+ const struct stacktrace_ops *ops;
107+ void *data;
108+};
109+
110+static asmlinkage int
111+dump_trace_unwind(struct unwind_frame_info *info, void *data)
112+{
113+ struct ops_and_data *oad = (struct ops_and_data *)data;
114+ int n = 0;
115+ unsigned long sp = UNW_SP(info);
116+
117+ if (arch_unw_user_mode(info))
118+ return -1;
119+ while (unwind(info) == 0 && UNW_PC(info)) {
120+ n++;
121+ oad->ops->address(oad->data, UNW_PC(info), 1);
122+ if (arch_unw_user_mode(info))
123+ break;
124+ if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1))
125+ && sp > UNW_SP(info))
126+ break;
127+ sp = UNW_SP(info);
128+ }
129+ return n;
130+}
131+
132 void dump_trace(struct task_struct *task, struct pt_regs *regs,
133 unsigned long *stack, unsigned long bp,
134 const struct stacktrace_ops *ops, void *data)
135@@ -163,6 +195,40 @@ void dump_trace(struct task_struct *task
136 if (!task)
137 task = current;
138
139+ if (call_trace >= 0) {
140+ int unw_ret = 0;
141+ struct unwind_frame_info info;
142+ struct ops_and_data oad = { .ops = ops, .data = data };
143+
144+ if (regs) {
145+ if (unwind_init_frame_info(&info, task, regs) == 0)
146+ unw_ret = dump_trace_unwind(&info, &oad);
147+ } else if (task == current)
148+ unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad);
149+ else {
150+ if (unwind_init_blocked(&info, task) == 0)
151+ unw_ret = dump_trace_unwind(&info, &oad);
152+ }
153+ if (unw_ret > 0) {
154+ if (call_trace == 1 && !arch_unw_user_mode(&info)) {
155+ ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n",
156+ UNW_PC(&info));
157+ if (UNW_SP(&info) >= PAGE_OFFSET) {
158+ ops->warning(data, "Leftover inexact backtrace:\n");
159+ stack = (void *)UNW_SP(&info);
160+ if (!stack)
161+ return;
162+ bp = UNW_FP(&info);
163+ } else
164+ ops->warning(data, "Full inexact backtrace again:\n");
165+ } else if (call_trace >= 1)
166+ return;
167+ else
168+ ops->warning(data, "Full inexact backtrace again:\n");
169+ } else
170+ ops->warning(data, "Inexact backtrace:\n");
171+ }
172+
173 if (!stack) {
174 unsigned long dummy;
175 stack = &dummy;
176@@ -1226,3 +1292,19 @@ static int __init code_bytes_setup(char
177 return 1;
178 }
179 __setup("code_bytes=", code_bytes_setup);
180+
181+#ifdef CONFIG_STACK_UNWIND
182+static int __init call_trace_setup(char *s)
183+{
184+ if (strcmp(s, "old") == 0)
185+ call_trace = -1;
186+ else if (strcmp(s, "both") == 0)
187+ call_trace = 0;
188+ else if (strcmp(s, "newfallback") == 0)
189+ call_trace = 1;
190+ else if (strcmp(s, "new") == 2)
191+ call_trace = 2;
192+ return 1;
193+}
194+__setup("call_trace=", call_trace_setup);
195+#endif
196--- sle11-2009-05-14.orig/arch/x86/kernel/traps_64-xen.c 2008-11-25 13:17:06.000000000 +0100
197+++ sle11-2009-05-14/arch/x86/kernel/traps_64-xen.c 2008-11-25 13:17:09.000000000 +0100
198@@ -59,6 +59,11 @@ int panic_on_unrecovered_nmi;
199 int panic_on_io_nmi;
200 int kstack_depth_to_print = 12;
201 static unsigned int code_bytes = 64;
202+#ifdef CONFIG_STACK_UNWIND
203+static int call_trace = 1;
204+#else
205+#define call_trace (-1)
206+#endif
207 static int ignore_nmis;
208 static int die_counter;
209
210@@ -165,6 +170,32 @@ static unsigned long *in_exception_stack
211 return NULL;
212 }
213
214+struct ops_and_data {
215+ const struct stacktrace_ops *ops;
216+ void *data;
217+};
218+
219+static int dump_trace_unwind(struct unwind_frame_info *info, void *context)
220+{
221+ struct ops_and_data *oad = (struct ops_and_data *)context;
222+ int n = 0;
223+ unsigned long sp = UNW_SP(info);
224+
225+ if (arch_unw_user_mode(info))
226+ return -1;
227+ while (unwind(info) == 0 && UNW_PC(info)) {
228+ n++;
229+ oad->ops->address(oad->data, UNW_PC(info), 1);
230+ if (arch_unw_user_mode(info))
231+ break;
232+ if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1))
233+ && sp > UNW_SP(info))
234+ break;
235+ sp = UNW_SP(info);
236+ }
237+ return n;
238+}
239+
240 /*
241 * x86-64 can have up to three kernel stacks:
242 * process stack
243@@ -229,6 +260,42 @@ void dump_trace(struct task_struct *task
244 if (!task)
245 task = current;
246
247+ if (call_trace >= 0) {
248+ int unw_ret = 0;
249+ struct unwind_frame_info info;
250+ struct ops_and_data oad = { .ops = ops, .data = data };
251+
252+ if (regs) {
253+ if (unwind_init_frame_info(&info, task, regs) == 0)
254+ unw_ret = dump_trace_unwind(&info, &oad);
255+ } else if (task == current)
256+ unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad);
257+ else {
258+ if (unwind_init_blocked(&info, task) == 0)
259+ unw_ret = dump_trace_unwind(&info, &oad);
260+ }
261+ if (unw_ret > 0) {
262+ if (call_trace == 1 && !arch_unw_user_mode(&info)) {
263+ ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n",
264+ UNW_PC(&info));
265+ if ((long)UNW_SP(&info) < 0) {
266+ ops->warning(data, "Leftover inexact backtrace:\n");
267+ stack = (unsigned long *)UNW_SP(&info);
268+ if (!stack) {
269+ put_cpu();
270+ return;
271+ }
272+ } else
273+ ops->warning(data, "Full inexact backtrace again:\n");
274+ } else if (call_trace >= 1) {
275+ put_cpu();
276+ return;
277+ } else
278+ ops->warning(data, "Full inexact backtrace again:\n");
279+ } else
280+ ops->warning(data, "Inexact backtrace:\n");
281+ }
282+
283 if (!stack) {
284 unsigned long dummy;
285 stack = &dummy;
286@@ -1242,3 +1309,21 @@ static int __init code_bytes_setup(char
287 return 1;
288 }
289 __setup("code_bytes=", code_bytes_setup);
290+
291+#ifdef CONFIG_STACK_UNWIND
292+static int __init call_trace_setup(char *s)
293+{
294+ if (!s)
295+ return -EINVAL;
296+ if (strcmp(s, "old") == 0)
297+ call_trace = -1;
298+ else if (strcmp(s, "both") == 0)
299+ call_trace = 0;
300+ else if (strcmp(s, "newfallback") == 0)
301+ call_trace = 1;
302+ else if (strcmp(s, "new") == 0)
303+ call_trace = 2;
304+ return 0;
305+}
306+early_param("call_trace", call_trace_setup);
307+#endif