Contents of /trunk/kernel26-xen/patches-2.6.25-r1/1034-2.6.25-xen-stack-unwind.patch
Parent Directory | Revision Log
Revision 609 -
(show annotations)
(download)
Fri May 23 17:35:37 2008 UTC (16 years, 4 months ago) by niro
File size: 8838 byte(s)
Fri May 23 17:35:37 2008 UTC (16 years, 4 months ago) by niro
File size: 8838 byte(s)
-using opensuse xen patchset, updated kernel configs
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 | Index: head-2008-03-06/arch/x86/kernel/entry_32-xen.S |
8 | =================================================================== |
9 | --- head-2008-03-06.orig/arch/x86/kernel/entry_32-xen.S 2008-03-06 10:51:44.000000000 +0100 |
10 | +++ head-2008-03-06/arch/x86/kernel/entry_32-xen.S 2008-03-06 10:52:39.000000000 +0100 |
11 | @@ -1252,6 +1252,38 @@ ENTRY(fixup_4gb_segment) |
12 | CFI_ENDPROC |
13 | END(spurious_interrupt_bug) |
14 | |
15 | +#ifdef CONFIG_STACK_UNWIND |
16 | +ENTRY(arch_unwind_init_running) |
17 | + CFI_STARTPROC |
18 | + movl 4(%esp), %edx |
19 | + movl (%esp), %ecx |
20 | + leal 4(%esp), %eax |
21 | + movl %ebx, PT_EBX(%edx) |
22 | + xorl %ebx, %ebx |
23 | + movl %ebx, PT_ECX(%edx) |
24 | + movl %ebx, PT_EDX(%edx) |
25 | + movl %esi, PT_ESI(%edx) |
26 | + movl %edi, PT_EDI(%edx) |
27 | + movl %ebp, PT_EBP(%edx) |
28 | + movl %ebx, PT_EAX(%edx) |
29 | + movl $__USER_DS, PT_DS(%edx) |
30 | + movl $__USER_DS, PT_ES(%edx) |
31 | + movl $__KERNEL_PERCPU, PT_FS(%edx) |
32 | + movl %ebx, PT_ORIG_EAX(%edx) |
33 | + movl %ecx, PT_EIP(%edx) |
34 | + movl 12(%esp), %ecx |
35 | + movl $__KERNEL_CS, PT_CS(%edx) |
36 | + movl %ebx, PT_EFLAGS(%edx) |
37 | + movl %eax, PT_OLDESP(%edx) |
38 | + movl 8(%esp), %eax |
39 | + movl %ecx, 8(%esp) |
40 | + movl PT_EBX(%edx), %ebx |
41 | + movl $__KERNEL_DS, PT_OLDSS(%edx) |
42 | + jmpl *%eax |
43 | + CFI_ENDPROC |
44 | +ENDPROC(arch_unwind_init_running) |
45 | +#endif |
46 | + |
47 | ENTRY(kernel_thread_helper) |
48 | pushl $0 # fake return address for unwinder |
49 | CFI_STARTPROC |
50 | Index: head-2008-03-06/arch/x86/kernel/entry_64-xen.S |
51 | =================================================================== |
52 | --- head-2008-03-06.orig/arch/x86/kernel/entry_64-xen.S 2008-03-06 10:52:04.000000000 +0100 |
53 | +++ head-2008-03-06/arch/x86/kernel/entry_64-xen.S 2008-03-06 10:52:39.000000000 +0100 |
54 | @@ -1258,3 +1258,36 @@ KPROBE_ENTRY(ignore_sysret) |
55 | HYPERVISOR_IRET 0 |
56 | CFI_ENDPROC |
57 | ENDPROC(ignore_sysret) |
58 | + |
59 | +#ifdef CONFIG_STACK_UNWIND |
60 | +ENTRY(arch_unwind_init_running) |
61 | + CFI_STARTPROC |
62 | + movq %r15, R15(%rdi) |
63 | + movq %r14, R14(%rdi) |
64 | + xchgq %rsi, %rdx |
65 | + movq %r13, R13(%rdi) |
66 | + movq %r12, R12(%rdi) |
67 | + xorl %eax, %eax |
68 | + movq %rbp, RBP(%rdi) |
69 | + movq %rbx, RBX(%rdi) |
70 | + movq (%rsp), %rcx |
71 | + movq %rax, R11(%rdi) |
72 | + movq %rax, R10(%rdi) |
73 | + movq %rax, R9(%rdi) |
74 | + movq %rax, R8(%rdi) |
75 | + movq %rax, RAX(%rdi) |
76 | + movq %rax, RCX(%rdi) |
77 | + movq %rax, RDX(%rdi) |
78 | + movq %rax, RSI(%rdi) |
79 | + movq %rax, RDI(%rdi) |
80 | + movq %rax, ORIG_RAX(%rdi) |
81 | + movq %rcx, RIP(%rdi) |
82 | + leaq 8(%rsp), %rcx |
83 | + movq $__KERNEL_CS, CS(%rdi) |
84 | + movq %rax, EFLAGS(%rdi) |
85 | + movq %rcx, RSP(%rdi) |
86 | + movq $__KERNEL_DS, SS(%rdi) |
87 | + jmpq *%rdx |
88 | + CFI_ENDPROC |
89 | +ENDPROC(arch_unwind_init_running) |
90 | +#endif |
91 | Index: head-2008-03-06/arch/x86/kernel/traps_32-xen.c |
92 | =================================================================== |
93 | --- head-2008-03-06.orig/arch/x86/kernel/traps_32-xen.c 2008-03-06 10:52:38.000000000 +0100 |
94 | +++ head-2008-03-06/arch/x86/kernel/traps_32-xen.c 2008-03-06 10:52:39.000000000 +0100 |
95 | @@ -109,6 +109,11 @@ asmlinkage void machine_check(void); |
96 | |
97 | int kstack_depth_to_print = 24; |
98 | static unsigned int code_bytes = 64; |
99 | +#ifdef CONFIG_STACK_UNWIND |
100 | +static int call_trace = 1; |
101 | +#else |
102 | +#define call_trace (-1) |
103 | +#endif |
104 | |
105 | void printk_address(unsigned long address, int reliable) |
106 | { |
107 | @@ -174,7 +179,32 @@ static inline unsigned long print_contex |
108 | return bp; |
109 | } |
110 | |
111 | -#define MSG(msg) ops->warning(data, msg) |
112 | +struct ops_and_data { |
113 | + const struct stacktrace_ops *ops; |
114 | + void *data; |
115 | +}; |
116 | + |
117 | +static asmlinkage int |
118 | +dump_trace_unwind(struct unwind_frame_info *info, void *data) |
119 | +{ |
120 | + struct ops_and_data *oad = (struct ops_and_data *)data; |
121 | + int n = 0; |
122 | + unsigned long sp = UNW_SP(info); |
123 | + |
124 | + if (arch_unw_user_mode(info)) |
125 | + return -1; |
126 | + while (unwind(info) == 0 && UNW_PC(info)) { |
127 | + n++; |
128 | + oad->ops->address(oad->data, UNW_PC(info), 1); |
129 | + if (arch_unw_user_mode(info)) |
130 | + break; |
131 | + if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1)) |
132 | + && sp > UNW_SP(info)) |
133 | + break; |
134 | + sp = UNW_SP(info); |
135 | + } |
136 | + return n; |
137 | +} |
138 | |
139 | void dump_trace(struct task_struct *task, struct pt_regs *regs, |
140 | unsigned long *stack, unsigned long bp, |
141 | @@ -183,6 +213,40 @@ void dump_trace(struct task_struct *task |
142 | if (!task) |
143 | task = current; |
144 | |
145 | + if (call_trace >= 0) { |
146 | + int unw_ret = 0; |
147 | + struct unwind_frame_info info; |
148 | + struct ops_and_data oad = { .ops = ops, .data = data }; |
149 | + |
150 | + if (regs) { |
151 | + if (unwind_init_frame_info(&info, task, regs) == 0) |
152 | + unw_ret = dump_trace_unwind(&info, &oad); |
153 | + } else if (task == current) |
154 | + unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad); |
155 | + else { |
156 | + if (unwind_init_blocked(&info, task) == 0) |
157 | + unw_ret = dump_trace_unwind(&info, &oad); |
158 | + } |
159 | + if (unw_ret > 0) { |
160 | + if (call_trace == 1 && !arch_unw_user_mode(&info)) { |
161 | + ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n", |
162 | + UNW_PC(&info)); |
163 | + if (UNW_SP(&info) >= PAGE_OFFSET) { |
164 | + ops->warning(data, "Leftover inexact backtrace:\n"); |
165 | + stack = (void *)UNW_SP(&info); |
166 | + if (!stack) |
167 | + return; |
168 | + bp = UNW_FP(&info); |
169 | + } else |
170 | + ops->warning(data, "Full inexact backtrace again:\n"); |
171 | + } else if (call_trace >= 1) |
172 | + return; |
173 | + else |
174 | + ops->warning(data, "Full inexact backtrace again:\n"); |
175 | + } else |
176 | + ops->warning(data, "Inexact backtrace:\n"); |
177 | + } |
178 | + |
179 | if (!stack) { |
180 | unsigned long dummy; |
181 | stack = &dummy; |
182 | @@ -1197,3 +1261,19 @@ static int __init code_bytes_setup(char |
183 | return 1; |
184 | } |
185 | __setup("code_bytes=", code_bytes_setup); |
186 | + |
187 | +#ifdef CONFIG_STACK_UNWIND |
188 | +static int __init call_trace_setup(char *s) |
189 | +{ |
190 | + if (strcmp(s, "old") == 0) |
191 | + call_trace = -1; |
192 | + else if (strcmp(s, "both") == 0) |
193 | + call_trace = 0; |
194 | + else if (strcmp(s, "newfallback") == 0) |
195 | + call_trace = 1; |
196 | + else if (strcmp(s, "new") == 2) |
197 | + call_trace = 2; |
198 | + return 1; |
199 | +} |
200 | +__setup("call_trace=", call_trace_setup); |
201 | +#endif |
202 | Index: head-2008-03-06/arch/x86/kernel/traps_64-xen.c |
203 | =================================================================== |
204 | --- head-2008-03-06.orig/arch/x86/kernel/traps_64-xen.c 2008-03-06 10:52:38.000000000 +0100 |
205 | +++ head-2008-03-06/arch/x86/kernel/traps_64-xen.c 2008-03-06 10:52:39.000000000 +0100 |
206 | @@ -99,6 +99,11 @@ static inline void preempt_conditional_c |
207 | } |
208 | |
209 | int kstack_depth_to_print = 12; |
210 | +#ifdef CONFIG_STACK_UNWIND |
211 | +static int call_trace = 1; |
212 | +#else |
213 | +#define call_trace (-1) |
214 | +#endif |
215 | |
216 | void printk_address(unsigned long address, int reliable) |
217 | { |
218 | @@ -204,7 +209,31 @@ static unsigned long *in_exception_stack |
219 | return NULL; |
220 | } |
221 | |
222 | -#define MSG(txt) ops->warning(data, txt) |
223 | +struct ops_and_data { |
224 | + const struct stacktrace_ops *ops; |
225 | + void *data; |
226 | +}; |
227 | + |
228 | +static int dump_trace_unwind(struct unwind_frame_info *info, void *context) |
229 | +{ |
230 | + struct ops_and_data *oad = (struct ops_and_data *)context; |
231 | + int n = 0; |
232 | + unsigned long sp = UNW_SP(info); |
233 | + |
234 | + if (arch_unw_user_mode(info)) |
235 | + return -1; |
236 | + while (unwind(info) == 0 && UNW_PC(info)) { |
237 | + n++; |
238 | + oad->ops->address(oad->data, UNW_PC(info), 1); |
239 | + if (arch_unw_user_mode(info)) |
240 | + break; |
241 | + if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1)) |
242 | + && sp > UNW_SP(info)) |
243 | + break; |
244 | + sp = UNW_SP(info); |
245 | + } |
246 | + return n; |
247 | +} |
248 | |
249 | /* |
250 | * x86-64 can have up to three kernel stacks: |
251 | @@ -271,6 +300,39 @@ void dump_trace(struct task_struct *tsk, |
252 | tsk = current; |
253 | tinfo = task_thread_info(tsk); |
254 | |
255 | + if (call_trace >= 0) { |
256 | + int unw_ret = 0; |
257 | + struct unwind_frame_info info; |
258 | + struct ops_and_data oad = { .ops = ops, .data = data }; |
259 | + |
260 | + if (regs) { |
261 | + if (unwind_init_frame_info(&info, tsk, regs) == 0) |
262 | + unw_ret = dump_trace_unwind(&info, &oad); |
263 | + } else if (tsk == current) |
264 | + unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad); |
265 | + else { |
266 | + if (unwind_init_blocked(&info, tsk) == 0) |
267 | + unw_ret = dump_trace_unwind(&info, &oad); |
268 | + } |
269 | + if (unw_ret > 0) { |
270 | + if (call_trace == 1 && !arch_unw_user_mode(&info)) { |
271 | + ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n", |
272 | + UNW_PC(&info)); |
273 | + if ((long)UNW_SP(&info) < 0) { |
274 | + ops->warning(data, "Leftover inexact backtrace:\n"); |
275 | + stack = (unsigned long *)UNW_SP(&info); |
276 | + if (!stack) |
277 | + return; |
278 | + } else |
279 | + ops->warning(data, "Full inexact backtrace again:\n"); |
280 | + } else if (call_trace >= 1) |
281 | + return; |
282 | + else |
283 | + ops->warning(data, "Full inexact backtrace again:\n"); |
284 | + } else |
285 | + ops->warning(data, "Inexact backtrace:\n"); |
286 | + } |
287 | + |
288 | if (!stack) { |
289 | unsigned long dummy; |
290 | stack = &dummy; |
291 | @@ -1215,3 +1277,21 @@ static int __init code_bytes_setup(char |
292 | return 1; |
293 | } |
294 | __setup("code_bytes=", code_bytes_setup); |
295 | + |
296 | +#ifdef CONFIG_STACK_UNWIND |
297 | +static int __init call_trace_setup(char *s) |
298 | +{ |
299 | + if (!s) |
300 | + return -EINVAL; |
301 | + if (strcmp(s, "old") == 0) |
302 | + call_trace = -1; |
303 | + else if (strcmp(s, "both") == 0) |
304 | + call_trace = 0; |
305 | + else if (strcmp(s, "newfallback") == 0) |
306 | + call_trace = 1; |
307 | + else if (strcmp(s, "new") == 0) |
308 | + call_trace = 2; |
309 | + return 0; |
310 | +} |
311 | +early_param("call_trace", call_trace_setup); |
312 | +#endif |