]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.xen/xen3-stack-unwind
Add a patch to fix Intel E100 wake-on-lan problems.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.xen / xen3-stack-unwind
1 Subject: DWARF2 EH-frame based stack unwinding
2 From: jbeulich@novell.com
3 Patch-mainline: no
4
5 Automatically 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