Annotation of /trunk/kernel26-xen/patches-2.6.25-r1/1034-2.6.25-xen-stack-unwind.patch
Parent Directory | Revision Log
Revision 609 -
(hide 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 | niro | 609 | 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 |