]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.25/patches.arch/x86-tracehook
Revert "Move xen patchset to new version's subdir."
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.arch / x86-tracehook
diff --git a/src/patches/suse-2.6.27.25/patches.arch/x86-tracehook b/src/patches/suse-2.6.27.25/patches.arch/x86-tracehook
new file mode 100644 (file)
index 0000000..339a259
--- /dev/null
@@ -0,0 +1,509 @@
+From: Roland McGrath <roland@redhat.com>
+Date: Sun Apr 20 14:35:12 2008 -0700
+Subject: x86 tracehook
+References: FATE#304321
+Patch-mainline: no
+
+Apply the changes from x86-utrace branch of
+git://git.kernel.org/pub/scm/linux/kernel/git/frob/linux-2.6-utrace
+plus later cleanups.
+
+Signed-off-by: Roland McGrath <roland@redhat.com>
+Signed-off-by: Petr Tesarik <ptesarik@suse.cz>
+
+---
+ arch/x86/Kconfig              |    1 
+ arch/x86/kernel/ptrace.c      |   34 +-----
+ arch/x86/kernel/signal_32.c   |   11 +-
+ arch/x86/kernel/signal_64.c   |   49 ++-------
+ include/asm-x86/ptrace.h      |    5 
+ include/asm-x86/syscall.h     |  213 ++++++++++++++++++++++++++++++++++++++++++
+ include/asm-x86/thread_info.h |    4 
+ 7 files changed, 251 insertions(+), 66 deletions(-)
+
+--- linux-2.6.27.orig/arch/x86/Kconfig 2008-10-20 11:46:16.000000000 +0200
++++ linux-2.6.27/arch/x86/Kconfig      2008-10-20 17:24:26.000000000 +0200
+@@ -29,6 +29,7 @@ config X86
+       select HAVE_FTRACE
+       select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64)
+       select HAVE_ARCH_KGDB if !X86_VOYAGER
++      select HAVE_ARCH_TRACEHOOK
+       select HAVE_GENERIC_DMA_COHERENT if X86_32
+       select HAVE_EFFICIENT_UNALIGNED_ACCESS
+--- linux-2.6.27.orig/arch/x86/kernel/ptrace.c 2008-10-20 11:46:16.000000000 +0200
++++ linux-2.6.27/arch/x86/kernel/ptrace.c      2008-10-20 11:46:16.000000000 +0200
+@@ -14,6 +14,7 @@
+ #include <linux/errno.h>
+ #include <linux/ptrace.h>
+ #include <linux/regset.h>
++#include <linux/tracehook.h>
+ #include <linux/user.h>
+ #include <linux/elf.h>
+ #include <linux/security.h>
+@@ -1375,30 +1376,6 @@ void send_sigtrap(struct task_struct *ts
+       force_sig_info(SIGTRAP, &info, tsk);
+ }
+-static void syscall_trace(struct pt_regs *regs)
+-{
+-      if (!(current->ptrace & PT_PTRACED))
+-              return;
+-
+-#if 0
+-      printk("trace %s ip %lx sp %lx ax %d origrax %d caller %lx tiflags %x ptrace %x\n",
+-             current->comm,
+-             regs->ip, regs->sp, regs->ax, regs->orig_ax, __builtin_return_address(0),
+-             current_thread_info()->flags, current->ptrace);
+-#endif
+-
+-      ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+-                              ? 0x80 : 0));
+-      /*
+-       * this isn't the same as continuing with a signal, but it will do
+-       * for normal use.  strace only continues with a signal if the
+-       * stopping signal is not SIGTRAP.  -brl
+-       */
+-      if (current->exit_code) {
+-              send_sig(current->exit_code, current, 1);
+-              current->exit_code = 0;
+-      }
+-}
+ #ifdef CONFIG_X86_32
+ # define IS_IA32      1
+@@ -1443,8 +1420,9 @@ asmregparm long syscall_trace_enter(stru
+       if (unlikely(test_thread_flag(TIF_SYSCALL_EMU)))
+               ret = -1L;
+-      if (ret || test_thread_flag(TIF_SYSCALL_TRACE))
+-              syscall_trace(regs);
++      if ((ret || test_thread_flag(TIF_SYSCALL_TRACE)) &&
++          tracehook_report_syscall_entry(regs))
++              ret = -1L;
+       if (unlikely(current->audit_context)) {
+               if (IS_IA32)
+@@ -1473,7 +1451,7 @@ asmregparm void syscall_trace_leave(stru
+               audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax);
+       if (test_thread_flag(TIF_SYSCALL_TRACE))
+-              syscall_trace(regs);
++              tracehook_report_syscall_exit(regs, 0);
+       /*
+        * If TIF_SYSCALL_EMU is set, we only get here because of
+@@ -1489,6 +1467,6 @@ asmregparm void syscall_trace_leave(stru
+        * system call instruction.
+        */
+       if (test_thread_flag(TIF_SINGLESTEP) &&
+-          (current->ptrace & PT_PTRACED))
++          tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL))
+               send_sigtrap(current, regs, 0);
+ }
+--- linux-2.6.27.orig/arch/x86/kernel/signal_32.c      2008-10-20 11:46:16.000000000 +0200
++++ linux-2.6.27/arch/x86/kernel/signal_32.c   2008-10-20 11:46:16.000000000 +0200
+@@ -17,6 +17,7 @@
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+ #include <linux/wait.h>
++#include <linux/tracehook.h>
+ #include <linux/elf.h>
+ #include <linux/smp.h>
+ #include <linux/mm.h>
+@@ -558,8 +559,6 @@ handle_signal(unsigned long sig, siginfo
+        * handler too.
+        */
+       regs->flags &= ~X86_EFLAGS_TF;
+-      if (test_thread_flag(TIF_SINGLESTEP))
+-              ptrace_notify(SIGTRAP);
+       spin_lock_irq(&current->sighand->siglock);
+       sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
+@@ -573,6 +572,9 @@ handle_signal(unsigned long sig, siginfo
+               current->instrumentation &= ~PTS_SELF;
+       }
++      tracehook_signal_handler(sig, info, ka, regs,
++                               test_thread_flag(TIF_SINGLESTEP));
++
+       return 0;
+ }
+@@ -666,5 +668,10 @@ do_notify_resume(struct pt_regs *regs, v
+       if (thread_info_flags & _TIF_SIGPENDING)
+               do_signal(regs);
++      if (thread_info_flags & _TIF_NOTIFY_RESUME) {
++              clear_thread_flag(TIF_NOTIFY_RESUME);
++              tracehook_notify_resume(regs);
++      }
++
+       clear_thread_flag(TIF_IRET);
+ }
+--- linux-2.6.27.orig/arch/x86/kernel/signal_64.c      2008-10-20 11:46:16.000000000 +0200
++++ linux-2.6.27/arch/x86/kernel/signal_64.c   2008-10-20 11:46:16.000000000 +0200
+@@ -15,6 +15,7 @@
+ #include <linux/errno.h>
+ #include <linux/wait.h>
+ #include <linux/ptrace.h>
++#include <linux/tracehook.h>
+ #include <linux/unistd.h>
+ #include <linux/stddef.h>
+ #include <linux/personality.h>
+@@ -26,6 +27,7 @@
+ #include <asm/proto.h>
+ #include <asm/ia32_unistd.h>
+ #include <asm/mce.h>
++#include <asm/syscall.h>
+ #include "sigframe.h"
+ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+@@ -355,35 +357,6 @@ give_sigsegv:
+ }
+ /*
+- * Return -1L or the syscall number that @regs is executing.
+- */
+-static long current_syscall(struct pt_regs *regs)
+-{
+-      /*
+-       * We always sign-extend a -1 value being set here,
+-       * so this is always either -1L or a syscall number.
+-       */
+-      return regs->orig_ax;
+-}
+-
+-/*
+- * Return a value that is -EFOO if the system call in @regs->orig_ax
+- * returned an error.  This only works for @regs from @current.
+- */
+-static long current_syscall_ret(struct pt_regs *regs)
+-{
+-#ifdef CONFIG_IA32_EMULATION
+-      if (test_thread_flag(TIF_IA32))
+-              /*
+-               * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
+-               * and will match correctly in comparisons.
+-               */
+-              return (int) regs->ax;
+-#endif
+-      return regs->ax;
+-}
+-
+-/*
+  * OK, we're invoking a handler
+  */   
+@@ -394,9 +367,9 @@ handle_signal(unsigned long sig, siginfo
+       int ret;
+       /* Are we from a system call? */
+-      if (current_syscall(regs) >= 0) {
++      if (syscall_get_nr(current, regs) >= 0) {
+               /* If so, check system call restarting.. */
+-              switch (current_syscall_ret(regs)) {
++              switch (syscall_get_error(current, regs)) {
+               case -ERESTART_RESTARTBLOCK:
+               case -ERESTARTNOHAND:
+                       regs->ax = -EINTR;
+@@ -453,8 +426,6 @@ handle_signal(unsigned long sig, siginfo
+                * handler too.
+                */
+               regs->flags &= ~X86_EFLAGS_TF;
+-              if (test_thread_flag(TIF_SINGLESTEP))
+-                      ptrace_notify(SIGTRAP);
+               spin_lock_irq(&current->sighand->siglock);
+               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+@@ -462,6 +433,9 @@ handle_signal(unsigned long sig, siginfo
+                       sigaddset(&current->blocked,sig);
+               recalc_sigpending();
+               spin_unlock_irq(&current->sighand->siglock);
++
++              tracehook_signal_handler(sig, info, ka, regs,
++                                       test_thread_flag(TIF_SINGLESTEP));
+       }
+       if (current->instrumentation & PTS_SELF) {
+@@ -523,9 +497,9 @@ static void do_signal(struct pt_regs *re
+       }
+       /* Did we come from a system call? */
+-      if (current_syscall(regs) >= 0) {
++      if (syscall_get_nr(current, regs) >= 0) {
+               /* Restart the system call - no handlers present */
+-              switch (current_syscall_ret(regs)) {
++              switch (syscall_get_error(current, regs)) {
+               case -ERESTARTNOHAND:
+               case -ERESTARTSYS:
+               case -ERESTARTNOINTR:
+@@ -563,6 +537,11 @@ void do_notify_resume(struct pt_regs *re
+       /* deal with pending signal delivery */
+       if (thread_info_flags & _TIF_SIGPENDING)
+               do_signal(regs);
++
++      if (thread_info_flags & _TIF_NOTIFY_RESUME) {
++              clear_thread_flag(TIF_NOTIFY_RESUME);
++              tracehook_notify_resume(regs);
++      }
+ }
+ void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
+--- linux-2.6.27.orig/include/asm-x86/ptrace.h 2008-10-10 00:13:53.000000000 +0200
++++ linux-2.6.27/include/asm-x86/ptrace.h      2008-10-20 17:23:29.000000000 +0200
+@@ -213,6 +213,11 @@ static inline unsigned long frame_pointe
+       return regs->bp;
+ }
++static inline unsigned long user_stack_pointer(struct pt_regs *regs)
++{
++      return regs->sp;
++}
++
+ /*
+  * These are defined as per linux/ptrace.h, which see.
+  */
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.27/include/asm-x86/syscall.h     2008-10-20 17:32:17.000000000 +0200
+@@ -0,0 +1,213 @@
++/*
++ * Access to user system call parameters and results
++ *
++ * Copyright (C) 2008 Red Hat, Inc.  All rights reserved.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU General Public License v.2.
++ *
++ * See asm-generic/syscall.h for descriptions of what we must do here.
++ */
++
++#ifndef _ASM_SYSCALL_H
++#define _ASM_SYSCALL_H        1
++
++#include <linux/sched.h>
++#include <linux/err.h>
++
++static inline long syscall_get_nr(struct task_struct *task,
++                                struct pt_regs *regs)
++{
++      /*
++       * We always sign-extend a -1 value being set here,
++       * so this is always either -1L or a syscall number.
++       */
++      return regs->orig_ax;
++}
++
++static inline void syscall_rollback(struct task_struct *task,
++                                  struct pt_regs *regs)
++{
++      regs->ax = regs->orig_ax;
++}
++
++static inline long syscall_get_error(struct task_struct *task,
++                                   struct pt_regs *regs)
++{
++      unsigned long error = regs->ax;
++#ifdef CONFIG_IA32_EMULATION
++      /*
++       * TS_COMPAT is set for 32-bit syscall entries and then
++       * remains set until we return to user mode.
++       */
++      if (task_thread_info(task)->status & TS_COMPAT)
++              /*
++               * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
++               * and will match correctly in comparisons.
++               */
++              error = (long) (int) error;
++#endif
++      return IS_ERR_VALUE(error) ? error : 0;
++}
++
++static inline long syscall_get_return_value(struct task_struct *task,
++                                          struct pt_regs *regs)
++{
++      return regs->ax;
++}
++
++static inline void syscall_set_return_value(struct task_struct *task,
++                                          struct pt_regs *regs,
++                                          int error, long val)
++{
++      regs->ax = (long) error ?: val;
++}
++
++#ifdef CONFIG_X86_32
++
++static inline void syscall_get_arguments(struct task_struct *task,
++                                       struct pt_regs *regs,
++                                       unsigned int i, unsigned int n,
++                                       unsigned long *args)
++{
++      BUG_ON(i + n > 6);
++      memcpy(args, &regs->bx + i, n * sizeof(args[0]));
++}
++
++static inline void syscall_set_arguments(struct task_struct *task,
++                                       struct pt_regs *regs,
++                                       unsigned int i, unsigned int n,
++                                       const unsigned long *args)
++{
++      BUG_ON(i + n > 6);
++      memcpy(&regs->bx + i, args, n * sizeof(args[0]));
++}
++
++#else  /* CONFIG_X86_64 */
++
++static inline void syscall_get_arguments(struct task_struct *task,
++                                       struct pt_regs *regs,
++                                       unsigned int i, unsigned int n,
++                                       unsigned long *args)
++{
++# ifdef CONFIG_IA32_EMULATION
++      if (task_thread_info(task)->status & TS_COMPAT)
++              switch (i) {
++              case 0:
++                      if (!n--) break;
++                      *args++ = regs->bx;
++              case 1:
++                      if (!n--) break;
++                      *args++ = regs->cx;
++              case 2:
++                      if (!n--) break;
++                      *args++ = regs->dx;
++              case 3:
++                      if (!n--) break;
++                      *args++ = regs->si;
++              case 4:
++                      if (!n--) break;
++                      *args++ = regs->di;
++              case 5:
++                      if (!n--) break;
++                      *args++ = regs->bp;
++              case 6:
++                      if (!n--) break;
++              default:
++                      BUG();
++                      break;
++              }
++      else
++# endif
++              switch (i) {
++              case 0:
++                      if (!n--) break;
++                      *args++ = regs->di;
++              case 1:
++                      if (!n--) break;
++                      *args++ = regs->si;
++              case 2:
++                      if (!n--) break;
++                      *args++ = regs->dx;
++              case 3:
++                      if (!n--) break;
++                      *args++ = regs->r10;
++              case 4:
++                      if (!n--) break;
++                      *args++ = regs->r8;
++              case 5:
++                      if (!n--) break;
++                      *args++ = regs->r9;
++              case 6:
++                      if (!n--) break;
++              default:
++                      BUG();
++                      break;
++              }
++}
++
++static inline void syscall_set_arguments(struct task_struct *task,
++                                       struct pt_regs *regs,
++                                       unsigned int i, unsigned int n,
++                                       const unsigned long *args)
++{
++# ifdef CONFIG_IA32_EMULATION
++      if (task_thread_info(task)->status & TS_COMPAT)
++              switch (i) {
++              case 0:
++                      if (!n--) break;
++                      regs->bx = *args++;
++              case 1:
++                      if (!n--) break;
++                      regs->cx = *args++;
++              case 2:
++                      if (!n--) break;
++                      regs->dx = *args++;
++              case 3:
++                      if (!n--) break;
++                      regs->si = *args++;
++              case 4:
++                      if (!n--) break;
++                      regs->di = *args++;
++              case 5:
++                      if (!n--) break;
++                      regs->bp = *args++;
++              case 6:
++                      if (!n--) break;
++              default:
++                      BUG();
++                      break;
++              }
++      else
++# endif
++              switch (i) {
++              case 0:
++                      if (!n--) break;
++                      regs->di = *args++;
++              case 1:
++                      if (!n--) break;
++                      regs->si = *args++;
++              case 2:
++                      if (!n--) break;
++                      regs->dx = *args++;
++              case 3:
++                      if (!n--) break;
++                      regs->r10 = *args++;
++              case 4:
++                      if (!n--) break;
++                      regs->r8 = *args++;
++              case 5:
++                      if (!n--) break;
++                      regs->r9 = *args++;
++              case 6:
++                      if (!n--) break;
++              default:
++                      BUG();
++                      break;
++              }
++}
++
++#endif        /* CONFIG_X86_32 */
++
++#endif        /* _ASM_SYSCALL_H */
+--- linux-2.6.27.orig/include/asm-x86/thread_info.h    2008-10-10 00:13:53.000000000 +0200
++++ linux-2.6.27/include/asm-x86/thread_info.h 2008-10-20 17:23:10.000000000 +0200
+@@ -71,6 +71,7 @@ struct thread_info {
+  * Warning: layout of LSW is hardcoded in entry.S
+  */
+ #define TIF_SYSCALL_TRACE     0       /* syscall trace active */
++#define TIF_NOTIFY_RESUME     1       /* callback before returning to user */
+ #define TIF_SIGPENDING                2       /* signal pending */
+ #define TIF_NEED_RESCHED      3       /* rescheduling necessary */
+ #define TIF_SINGLESTEP                4       /* reenable singlestep on user return*/
+@@ -93,6 +94,7 @@ struct thread_info {
+ #define TIF_BTS_TRACE_TS      27      /* record scheduling event timestamps */
+ #define _TIF_SYSCALL_TRACE    (1 << TIF_SYSCALL_TRACE)
++#define _TIF_NOTIFY_RESUME    (1 << TIF_NOTIFY_RESUME)
+ #define _TIF_SIGPENDING               (1 << TIF_SIGPENDING)
+ #define _TIF_SINGLESTEP               (1 << TIF_SINGLESTEP)
+ #define _TIF_NEED_RESCHED     (1 << TIF_NEED_RESCHED)
+@@ -133,7 +135,7 @@ struct thread_info {
+ /* Only used for 64 bit */
+ #define _TIF_DO_NOTIFY_MASK                                           \
+-      (_TIF_SIGPENDING|_TIF_MCE_NOTIFY)
++      (_TIF_SIGPENDING|_TIF_MCE_NOTIFY|_TIF_NOTIFY_RESUME)
+ /* flags to check in __switch_to() */
+ #define _TIF_WORK_CTXSW                                                       \