]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.39/patches.arch/x86-tracehook
Add a patch to fix Intel E100 wake-on-lan problems.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.arch / x86-tracehook
1 From: Roland McGrath <roland@redhat.com>
2 Date: Sun Apr 20 14:35:12 2008 -0700
3 Subject: x86 tracehook
4 References: FATE#304321
5 Patch-mainline: no
6
7 Apply the changes from x86-utrace branch of
8 git://git.kernel.org/pub/scm/linux/kernel/git/frob/linux-2.6-utrace
9 plus later cleanups.
10
11 Signed-off-by: Roland McGrath <roland@redhat.com>
12 Signed-off-by: Petr Tesarik <ptesarik@suse.cz>
13
14 ---
15 arch/x86/Kconfig | 1
16 arch/x86/kernel/ptrace.c | 34 +-----
17 arch/x86/kernel/signal_32.c | 11 +-
18 arch/x86/kernel/signal_64.c | 49 ++-------
19 include/asm-x86/ptrace.h | 5
20 include/asm-x86/syscall.h | 213 ++++++++++++++++++++++++++++++++++++++++++
21 include/asm-x86/thread_info.h | 4
22 7 files changed, 251 insertions(+), 66 deletions(-)
23
24 --- linux-2.6.27.orig/arch/x86/Kconfig 2008-10-20 11:46:16.000000000 +0200
25 +++ linux-2.6.27/arch/x86/Kconfig 2008-10-20 17:24:26.000000000 +0200
26 @@ -29,6 +29,7 @@ config X86
27 select HAVE_FTRACE
28 select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64)
29 select HAVE_ARCH_KGDB if !X86_VOYAGER
30 + select HAVE_ARCH_TRACEHOOK
31 select HAVE_GENERIC_DMA_COHERENT if X86_32
32 select HAVE_EFFICIENT_UNALIGNED_ACCESS
33
34 --- linux-2.6.27.orig/arch/x86/kernel/ptrace.c 2008-10-20 11:46:16.000000000 +0200
35 +++ linux-2.6.27/arch/x86/kernel/ptrace.c 2008-10-20 11:46:16.000000000 +0200
36 @@ -14,6 +14,7 @@
37 #include <linux/errno.h>
38 #include <linux/ptrace.h>
39 #include <linux/regset.h>
40 +#include <linux/tracehook.h>
41 #include <linux/user.h>
42 #include <linux/elf.h>
43 #include <linux/security.h>
44 @@ -1375,30 +1376,6 @@ void send_sigtrap(struct task_struct *ts
45 force_sig_info(SIGTRAP, &info, tsk);
46 }
47
48 -static void syscall_trace(struct pt_regs *regs)
49 -{
50 - if (!(current->ptrace & PT_PTRACED))
51 - return;
52 -
53 -#if 0
54 - printk("trace %s ip %lx sp %lx ax %d origrax %d caller %lx tiflags %x ptrace %x\n",
55 - current->comm,
56 - regs->ip, regs->sp, regs->ax, regs->orig_ax, __builtin_return_address(0),
57 - current_thread_info()->flags, current->ptrace);
58 -#endif
59 -
60 - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
61 - ? 0x80 : 0));
62 - /*
63 - * this isn't the same as continuing with a signal, but it will do
64 - * for normal use. strace only continues with a signal if the
65 - * stopping signal is not SIGTRAP. -brl
66 - */
67 - if (current->exit_code) {
68 - send_sig(current->exit_code, current, 1);
69 - current->exit_code = 0;
70 - }
71 -}
72
73 #ifdef CONFIG_X86_32
74 # define IS_IA32 1
75 @@ -1443,8 +1420,9 @@ asmregparm long syscall_trace_enter(stru
76 if (unlikely(test_thread_flag(TIF_SYSCALL_EMU)))
77 ret = -1L;
78
79 - if (ret || test_thread_flag(TIF_SYSCALL_TRACE))
80 - syscall_trace(regs);
81 + if ((ret || test_thread_flag(TIF_SYSCALL_TRACE)) &&
82 + tracehook_report_syscall_entry(regs))
83 + ret = -1L;
84
85 if (unlikely(current->audit_context)) {
86 if (IS_IA32)
87 @@ -1473,7 +1451,7 @@ asmregparm void syscall_trace_leave(stru
88 audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax);
89
90 if (test_thread_flag(TIF_SYSCALL_TRACE))
91 - syscall_trace(regs);
92 + tracehook_report_syscall_exit(regs, 0);
93
94 /*
95 * If TIF_SYSCALL_EMU is set, we only get here because of
96 @@ -1489,6 +1467,6 @@ asmregparm void syscall_trace_leave(stru
97 * system call instruction.
98 */
99 if (test_thread_flag(TIF_SINGLESTEP) &&
100 - (current->ptrace & PT_PTRACED))
101 + tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL))
102 send_sigtrap(current, regs, 0);
103 }
104 --- linux-2.6.27.orig/arch/x86/kernel/signal_32.c 2008-10-20 11:46:16.000000000 +0200
105 +++ linux-2.6.27/arch/x86/kernel/signal_32.c 2008-10-20 11:46:16.000000000 +0200
106 @@ -17,6 +17,7 @@
107 #include <linux/errno.h>
108 #include <linux/sched.h>
109 #include <linux/wait.h>
110 +#include <linux/tracehook.h>
111 #include <linux/elf.h>
112 #include <linux/smp.h>
113 #include <linux/mm.h>
114 @@ -558,8 +559,6 @@ handle_signal(unsigned long sig, siginfo
115 * handler too.
116 */
117 regs->flags &= ~X86_EFLAGS_TF;
118 - if (test_thread_flag(TIF_SINGLESTEP))
119 - ptrace_notify(SIGTRAP);
120
121 spin_lock_irq(&current->sighand->siglock);
122 sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
123 @@ -573,6 +572,9 @@ handle_signal(unsigned long sig, siginfo
124 current->instrumentation &= ~PTS_SELF;
125 }
126
127 + tracehook_signal_handler(sig, info, ka, regs,
128 + test_thread_flag(TIF_SINGLESTEP));
129 +
130 return 0;
131 }
132
133 @@ -666,5 +668,10 @@ do_notify_resume(struct pt_regs *regs, v
134 if (thread_info_flags & _TIF_SIGPENDING)
135 do_signal(regs);
136
137 + if (thread_info_flags & _TIF_NOTIFY_RESUME) {
138 + clear_thread_flag(TIF_NOTIFY_RESUME);
139 + tracehook_notify_resume(regs);
140 + }
141 +
142 clear_thread_flag(TIF_IRET);
143 }
144 --- linux-2.6.27.orig/arch/x86/kernel/signal_64.c 2008-10-20 11:46:16.000000000 +0200
145 +++ linux-2.6.27/arch/x86/kernel/signal_64.c 2008-10-20 11:46:16.000000000 +0200
146 @@ -15,6 +15,7 @@
147 #include <linux/errno.h>
148 #include <linux/wait.h>
149 #include <linux/ptrace.h>
150 +#include <linux/tracehook.h>
151 #include <linux/unistd.h>
152 #include <linux/stddef.h>
153 #include <linux/personality.h>
154 @@ -26,6 +27,7 @@
155 #include <asm/proto.h>
156 #include <asm/ia32_unistd.h>
157 #include <asm/mce.h>
158 +#include <asm/syscall.h>
159 #include "sigframe.h"
160
161 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
162 @@ -355,35 +357,6 @@ give_sigsegv:
163 }
164
165 /*
166 - * Return -1L or the syscall number that @regs is executing.
167 - */
168 -static long current_syscall(struct pt_regs *regs)
169 -{
170 - /*
171 - * We always sign-extend a -1 value being set here,
172 - * so this is always either -1L or a syscall number.
173 - */
174 - return regs->orig_ax;
175 -}
176 -
177 -/*
178 - * Return a value that is -EFOO if the system call in @regs->orig_ax
179 - * returned an error. This only works for @regs from @current.
180 - */
181 -static long current_syscall_ret(struct pt_regs *regs)
182 -{
183 -#ifdef CONFIG_IA32_EMULATION
184 - if (test_thread_flag(TIF_IA32))
185 - /*
186 - * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
187 - * and will match correctly in comparisons.
188 - */
189 - return (int) regs->ax;
190 -#endif
191 - return regs->ax;
192 -}
193 -
194 -/*
195 * OK, we're invoking a handler
196 */
197
198 @@ -394,9 +367,9 @@ handle_signal(unsigned long sig, siginfo
199 int ret;
200
201 /* Are we from a system call? */
202 - if (current_syscall(regs) >= 0) {
203 + if (syscall_get_nr(current, regs) >= 0) {
204 /* If so, check system call restarting.. */
205 - switch (current_syscall_ret(regs)) {
206 + switch (syscall_get_error(current, regs)) {
207 case -ERESTART_RESTARTBLOCK:
208 case -ERESTARTNOHAND:
209 regs->ax = -EINTR;
210 @@ -453,8 +426,6 @@ handle_signal(unsigned long sig, siginfo
211 * handler too.
212 */
213 regs->flags &= ~X86_EFLAGS_TF;
214 - if (test_thread_flag(TIF_SINGLESTEP))
215 - ptrace_notify(SIGTRAP);
216
217 spin_lock_irq(&current->sighand->siglock);
218 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
219 @@ -462,6 +433,9 @@ handle_signal(unsigned long sig, siginfo
220 sigaddset(&current->blocked,sig);
221 recalc_sigpending();
222 spin_unlock_irq(&current->sighand->siglock);
223 +
224 + tracehook_signal_handler(sig, info, ka, regs,
225 + test_thread_flag(TIF_SINGLESTEP));
226 }
227
228 if (current->instrumentation & PTS_SELF) {
229 @@ -523,9 +497,9 @@ static void do_signal(struct pt_regs *re
230 }
231
232 /* Did we come from a system call? */
233 - if (current_syscall(regs) >= 0) {
234 + if (syscall_get_nr(current, regs) >= 0) {
235 /* Restart the system call - no handlers present */
236 - switch (current_syscall_ret(regs)) {
237 + switch (syscall_get_error(current, regs)) {
238 case -ERESTARTNOHAND:
239 case -ERESTARTSYS:
240 case -ERESTARTNOINTR:
241 @@ -563,6 +537,11 @@ void do_notify_resume(struct pt_regs *re
242 /* deal with pending signal delivery */
243 if (thread_info_flags & _TIF_SIGPENDING)
244 do_signal(regs);
245 +
246 + if (thread_info_flags & _TIF_NOTIFY_RESUME) {
247 + clear_thread_flag(TIF_NOTIFY_RESUME);
248 + tracehook_notify_resume(regs);
249 + }
250 }
251
252 void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
253 --- linux-2.6.27.orig/include/asm-x86/ptrace.h 2008-10-10 00:13:53.000000000 +0200
254 +++ linux-2.6.27/include/asm-x86/ptrace.h 2008-10-20 17:23:29.000000000 +0200
255 @@ -213,6 +213,11 @@ static inline unsigned long frame_pointe
256 return regs->bp;
257 }
258
259 +static inline unsigned long user_stack_pointer(struct pt_regs *regs)
260 +{
261 + return regs->sp;
262 +}
263 +
264 /*
265 * These are defined as per linux/ptrace.h, which see.
266 */
267 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
268 +++ linux-2.6.27/include/asm-x86/syscall.h 2008-10-20 17:32:17.000000000 +0200
269 @@ -0,0 +1,213 @@
270 +/*
271 + * Access to user system call parameters and results
272 + *
273 + * Copyright (C) 2008 Red Hat, Inc. All rights reserved.
274 + *
275 + * This copyrighted material is made available to anyone wishing to use,
276 + * modify, copy, or redistribute it subject to the terms and conditions
277 + * of the GNU General Public License v.2.
278 + *
279 + * See asm-generic/syscall.h for descriptions of what we must do here.
280 + */
281 +
282 +#ifndef _ASM_SYSCALL_H
283 +#define _ASM_SYSCALL_H 1
284 +
285 +#include <linux/sched.h>
286 +#include <linux/err.h>
287 +
288 +static inline long syscall_get_nr(struct task_struct *task,
289 + struct pt_regs *regs)
290 +{
291 + /*
292 + * We always sign-extend a -1 value being set here,
293 + * so this is always either -1L or a syscall number.
294 + */
295 + return regs->orig_ax;
296 +}
297 +
298 +static inline void syscall_rollback(struct task_struct *task,
299 + struct pt_regs *regs)
300 +{
301 + regs->ax = regs->orig_ax;
302 +}
303 +
304 +static inline long syscall_get_error(struct task_struct *task,
305 + struct pt_regs *regs)
306 +{
307 + unsigned long error = regs->ax;
308 +#ifdef CONFIG_IA32_EMULATION
309 + /*
310 + * TS_COMPAT is set for 32-bit syscall entries and then
311 + * remains set until we return to user mode.
312 + */
313 + if (task_thread_info(task)->status & TS_COMPAT)
314 + /*
315 + * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
316 + * and will match correctly in comparisons.
317 + */
318 + error = (long) (int) error;
319 +#endif
320 + return IS_ERR_VALUE(error) ? error : 0;
321 +}
322 +
323 +static inline long syscall_get_return_value(struct task_struct *task,
324 + struct pt_regs *regs)
325 +{
326 + return regs->ax;
327 +}
328 +
329 +static inline void syscall_set_return_value(struct task_struct *task,
330 + struct pt_regs *regs,
331 + int error, long val)
332 +{
333 + regs->ax = (long) error ?: val;
334 +}
335 +
336 +#ifdef CONFIG_X86_32
337 +
338 +static inline void syscall_get_arguments(struct task_struct *task,
339 + struct pt_regs *regs,
340 + unsigned int i, unsigned int n,
341 + unsigned long *args)
342 +{
343 + BUG_ON(i + n > 6);
344 + memcpy(args, &regs->bx + i, n * sizeof(args[0]));
345 +}
346 +
347 +static inline void syscall_set_arguments(struct task_struct *task,
348 + struct pt_regs *regs,
349 + unsigned int i, unsigned int n,
350 + const unsigned long *args)
351 +{
352 + BUG_ON(i + n > 6);
353 + memcpy(&regs->bx + i, args, n * sizeof(args[0]));
354 +}
355 +
356 +#else /* CONFIG_X86_64 */
357 +
358 +static inline void syscall_get_arguments(struct task_struct *task,
359 + struct pt_regs *regs,
360 + unsigned int i, unsigned int n,
361 + unsigned long *args)
362 +{
363 +# ifdef CONFIG_IA32_EMULATION
364 + if (task_thread_info(task)->status & TS_COMPAT)
365 + switch (i) {
366 + case 0:
367 + if (!n--) break;
368 + *args++ = regs->bx;
369 + case 1:
370 + if (!n--) break;
371 + *args++ = regs->cx;
372 + case 2:
373 + if (!n--) break;
374 + *args++ = regs->dx;
375 + case 3:
376 + if (!n--) break;
377 + *args++ = regs->si;
378 + case 4:
379 + if (!n--) break;
380 + *args++ = regs->di;
381 + case 5:
382 + if (!n--) break;
383 + *args++ = regs->bp;
384 + case 6:
385 + if (!n--) break;
386 + default:
387 + BUG();
388 + break;
389 + }
390 + else
391 +# endif
392 + switch (i) {
393 + case 0:
394 + if (!n--) break;
395 + *args++ = regs->di;
396 + case 1:
397 + if (!n--) break;
398 + *args++ = regs->si;
399 + case 2:
400 + if (!n--) break;
401 + *args++ = regs->dx;
402 + case 3:
403 + if (!n--) break;
404 + *args++ = regs->r10;
405 + case 4:
406 + if (!n--) break;
407 + *args++ = regs->r8;
408 + case 5:
409 + if (!n--) break;
410 + *args++ = regs->r9;
411 + case 6:
412 + if (!n--) break;
413 + default:
414 + BUG();
415 + break;
416 + }
417 +}
418 +
419 +static inline void syscall_set_arguments(struct task_struct *task,
420 + struct pt_regs *regs,
421 + unsigned int i, unsigned int n,
422 + const unsigned long *args)
423 +{
424 +# ifdef CONFIG_IA32_EMULATION
425 + if (task_thread_info(task)->status & TS_COMPAT)
426 + switch (i) {
427 + case 0:
428 + if (!n--) break;
429 + regs->bx = *args++;
430 + case 1:
431 + if (!n--) break;
432 + regs->cx = *args++;
433 + case 2:
434 + if (!n--) break;
435 + regs->dx = *args++;
436 + case 3:
437 + if (!n--) break;
438 + regs->si = *args++;
439 + case 4:
440 + if (!n--) break;
441 + regs->di = *args++;
442 + case 5:
443 + if (!n--) break;
444 + regs->bp = *args++;
445 + case 6:
446 + if (!n--) break;
447 + default:
448 + BUG();
449 + break;
450 + }
451 + else
452 +# endif
453 + switch (i) {
454 + case 0:
455 + if (!n--) break;
456 + regs->di = *args++;
457 + case 1:
458 + if (!n--) break;
459 + regs->si = *args++;
460 + case 2:
461 + if (!n--) break;
462 + regs->dx = *args++;
463 + case 3:
464 + if (!n--) break;
465 + regs->r10 = *args++;
466 + case 4:
467 + if (!n--) break;
468 + regs->r8 = *args++;
469 + case 5:
470 + if (!n--) break;
471 + regs->r9 = *args++;
472 + case 6:
473 + if (!n--) break;
474 + default:
475 + BUG();
476 + break;
477 + }
478 +}
479 +
480 +#endif /* CONFIG_X86_32 */
481 +
482 +#endif /* _ASM_SYSCALL_H */
483 --- linux-2.6.27.orig/include/asm-x86/thread_info.h 2008-10-10 00:13:53.000000000 +0200
484 +++ linux-2.6.27/include/asm-x86/thread_info.h 2008-10-20 17:23:10.000000000 +0200
485 @@ -71,6 +71,7 @@ struct thread_info {
486 * Warning: layout of LSW is hardcoded in entry.S
487 */
488 #define TIF_SYSCALL_TRACE 0 /* syscall trace active */
489 +#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
490 #define TIF_SIGPENDING 2 /* signal pending */
491 #define TIF_NEED_RESCHED 3 /* rescheduling necessary */
492 #define TIF_SINGLESTEP 4 /* reenable singlestep on user return*/
493 @@ -93,6 +94,7 @@ struct thread_info {
494 #define TIF_BTS_TRACE_TS 27 /* record scheduling event timestamps */
495
496 #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
497 +#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
498 #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
499 #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
500 #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
501 @@ -133,7 +135,7 @@ struct thread_info {
502
503 /* Only used for 64 bit */
504 #define _TIF_DO_NOTIFY_MASK \
505 - (_TIF_SIGPENDING|_TIF_MCE_NOTIFY)
506 + (_TIF_SIGPENDING|_TIF_MCE_NOTIFY|_TIF_NOTIFY_RESUME)
507
508 /* flags to check in __switch_to() */
509 #define _TIF_WORK_CTXSW \