Magellan Linux

Contents of /trunk/kernel26-xen/patches-2.6.25-r1/1034-2.6.25-xen-stack-unwind.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 609 - (show annotations) (download)
Fri May 23 17:35:37 2008 UTC (15 years, 11 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