]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge branch 'for-arm' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal...
authorRussell King <rmk+kernel@arm.linux.org.uk>
Tue, 29 May 2012 21:13:55 +0000 (22:13 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Tue, 29 May 2012 21:13:55 +0000 (22:13 +0100)
Conflicts:
arch/arm/kernel/ptrace.c

1  2 
arch/arm/include/asm/thread_info.h
arch/arm/kernel/entry-common.S
arch/arm/kernel/ptrace.c
arch/arm/kernel/signal.c
arch/arm/kernel/traps.c

index 68388eb4946bda7a26a6c06868c51b890411a5a6,ba6bb7baaddaf40c00c0fbe812ba3352586cc3ea..b79f8e97f7755f22d82ae20ee00442cd11f7af02
@@@ -148,12 -148,12 +148,13 @@@ extern int vfp_restore_user_hwstate(str
  #define TIF_NOTIFY_RESUME     2       /* callback before returning to user */
  #define TIF_SYSCALL_TRACE     8
  #define TIF_SYSCALL_AUDIT     9
+ #define TIF_SYSCALL_RESTARTSYS        10
  #define TIF_POLLING_NRFLAG    16
  #define TIF_USING_IWMMXT      17
  #define TIF_MEMDIE            18      /* is terminating due to OOM killer */
  #define TIF_RESTORE_SIGMASK   20
  #define TIF_SECCOMP           21
 +#define TIF_SWITCH_MM         22      /* deferred switch_mm */
  
  #define _TIF_SIGPENDING               (1 << TIF_SIGPENDING)
  #define _TIF_NEED_RESCHED     (1 << TIF_NEED_RESCHED)
  #define _TIF_SYSCALL_AUDIT    (1 << TIF_SYSCALL_AUDIT)
  #define _TIF_POLLING_NRFLAG   (1 << TIF_POLLING_NRFLAG)
  #define _TIF_USING_IWMMXT     (1 << TIF_USING_IWMMXT)
- #define _TIF_RESTORE_SIGMASK  (1 << TIF_RESTORE_SIGMASK)
  #define _TIF_SECCOMP          (1 << TIF_SECCOMP)
+ #define _TIF_SYSCALL_RESTARTSYS       (1 << TIF_SYSCALL_RESTARTSYS)
  
  /* Checks for any syscall work in entry-common.S */
- #define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT)
+ #define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
+                          _TIF_SYSCALL_RESTARTSYS)
  
  /*
   * Change these and you break ASM code in entry-common.S
   */
- #define _TIF_WORK_MASK                0x000000ff
+ #define _TIF_WORK_MASK                (_TIF_NEED_RESCHED | _TIF_SIGPENDING | _TIF_NOTIFY_RESUME)
  
  #endif /* __KERNEL__ */
  #endif /* __ASM_ARM_THREAD_INFO_H */
index 7bd2d3cb8957d2aeb6ba85baa2a5f6be49c1d3b8,b669b49d7cc412026c46338a5c03079f26051b91..4afed88d250a6f6127a8a42a7a3462394b078bfc
@@@ -53,9 -53,13 +53,13 @@@ fast_work_pending
  work_pending:
        tst     r1, #_TIF_NEED_RESCHED
        bne     work_resched
-       tst     r1, #_TIF_SIGPENDING|_TIF_NOTIFY_RESUME
-       beq     no_work_pending
+       /*
+        * TIF_SIGPENDING or TIF_NOTIFY_RESUME must've been set if we got here
+        */
+       ldr     r2, [sp, #S_PSR]
        mov     r0, sp                          @ 'regs'
+       tst     r2, #15                         @ are we returning to user mode?
+       bne     no_work_pending                 @ no?  just leave, then...
        mov     r2, why                         @ 'syscall'
        tst     r1, #_TIF_SIGPENDING            @ delivering a signal?
        movne   why, #0                         @ prevent further restarts
@@@ -335,6 -339,20 +339,6 @@@ ENDPROC(ftrace_stub
   *-----------------------------------------------------------------------------
   */
  
 -      /* If we're optimising for StrongARM the resulting code won't 
 -         run on an ARM7 and we can save a couple of instructions.  
 -                                                              --pb */
 -#ifdef CONFIG_CPU_ARM710
 -#define A710(code...) code
 -.Larm710bug:
 -      ldmia   sp, {r0 - lr}^                  @ Get calling r0 - lr
 -      mov     r0, r0
 -      add     sp, sp, #S_FRAME_SIZE
 -      subs    pc, lr, #4
 -#else
 -#define A710(code...)
 -#endif
 -
        .align  5
  ENTRY(vector_swi)
        sub     sp, sp, #S_FRAME_SIZE
        ldreq   r10, [lr, #-4]                  @ get SWI instruction
  #else
        ldr     r10, [lr, #-4]                  @ get SWI instruction
 -  A710(       and     ip, r10, #0x0f000000            @ check for SWI         )
 -  A710(       teq     ip, #0x0f000000                                         )
 -  A710(       bne     .Larm710bug                                             )
  #endif
  #ifdef CONFIG_CPU_ENDIAN_BE8
        rev     r10, r10                        @ little endian instruction
        /*
         * Pure EABI user space always put syscall number into scno (r7).
         */
 -  A710(       ldr     ip, [lr, #-4]                   @ get SWI instruction   )
 -  A710(       and     ip, ip, #0x0f000000             @ check for SWI         )
 -  A710(       teq     ip, #0x0f000000                                         )
 -  A710(       bne     .Larm710bug                                             )
 -
  #elif defined(CONFIG_ARM_THUMB)
 -
        /* Legacy ABI only, possibly thumb mode. */
        tst     r8, #PSR_T_BIT                  @ this is SPSR from save_user_regs
        addne   scno, r7, #__NR_SYSCALL_BASE    @ put OS number in
        ldreq   scno, [lr, #-4]
  
  #else
 -
        /* Legacy ABI only. */
        ldr     scno, [lr, #-4]                 @ get SWI instruction
 -  A710(       and     ip, scno, #0x0f000000           @ check for SWI         )
 -  A710(       teq     ip, #0x0f000000                                         )
 -  A710(       bne     .Larm710bug                                             )
 -
  #endif
  
  #ifdef CONFIG_ALIGNMENT_TRAP
diff --combined arch/arm/kernel/ptrace.c
index 14e38261cd31db9d852db2eb0b8046251a04613d,688a0a970c71ba0668ec2f56af31fe4fdf77b38c..5700a7ae7f0bc1511ae048d7a3f025c401e5729c
@@@ -24,7 -24,7 +24,8 @@@
  #include <linux/hw_breakpoint.h>
  #include <linux/regset.h>
  #include <linux/audit.h>
 +#include <linux/tracehook.h>
+ #include <linux/unistd.h>
  
  #include <asm/pgtable.h>
  #include <asm/traps.h>
@@@ -917,8 -917,12 +918,10 @@@ asmlinkage int syscall_trace(int why, s
                audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0,
                                    regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);
  
+       if (why == 0 && test_and_clear_thread_flag(TIF_SYSCALL_RESTARTSYS))
+               scno = __NR_restart_syscall - __NR_SYSCALL_BASE;
        if (!test_thread_flag(TIF_SYSCALL_TRACE))
                return scno;
 -      if (!(current->ptrace & PT_PTRACED))
 -              return scno;
  
        current_thread_info()->syscall = scno;
  
         */
        ip = regs->ARM_ip;
        regs->ARM_ip = why;
 -      ptrace_report_syscall(regs);
 +
 +      if (why)
 +              tracehook_report_syscall_exit(regs, 0);
 +      else if (tracehook_report_syscall_entry(regs))
 +              current_thread_info()->syscall = -1;
 +
        regs->ARM_ip = ip;
  
        return current_thread_info()->syscall;
diff --combined arch/arm/kernel/signal.c
index 73d9a420850def55f6ea65cc1b00aa85c6d3245f,869c4988fefcdc346fc802f84d5c288e57eb580e..b7ffda1ad8f23d278609a3ca4992ed05f337a36f
@@@ -29,7 -29,6 +29,6 @@@
   */
  #define SWI_SYS_SIGRETURN     (0xef000000|(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE))
  #define SWI_SYS_RT_SIGRETURN  (0xef000000|(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE))
- #define SWI_SYS_RESTART               (0xef000000|__NR_restart_syscall|__NR_OABI_SYSCALL_BASE)
  
  /*
   * With EABI, the syscall number has to be loaded into r7.
@@@ -49,18 -48,6 +48,6 @@@ const unsigned long sigreturn_codes[7] 
        MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
  };
  
- /*
-  * Either we support OABI only, or we have EABI with the OABI
-  * compat layer enabled.  In the later case we don't know if
-  * user space is EABI or not, and if not we must not clobber r7.
-  * Always using the OABI syscall solves that issue and works for
-  * all those cases.
-  */
- const unsigned long syscall_restart_code[2] = {
-       SWI_SYS_RESTART,        /* swi  __NR_restart_syscall */
-       0xe49df004,             /* ldr  pc, [sp], #4 */
- };
  /*
   * atomically swap in the new signal mask, and wait for a signal.
   */
@@@ -91,10 -78,10 +78,10 @@@ sys_sigaction(int sig, const struct old
                old_sigset_t mask;
                if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
                    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
-                   __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+                   __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
+                   __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
+                   __get_user(mask, &act->sa_mask))
                        return -EFAULT;
-               __get_user(new_ka.sa.sa_flags, &act->sa_flags);
-               __get_user(mask, &act->sa_mask);
                siginitset(&new_ka.sa.sa_mask, mask);
        }
  
        if (!ret && oact) {
                if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
                    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-                   __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+                   __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
+                   __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
+                   __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
                        return -EFAULT;
-               __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-               __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
        }
  
        return ret;
@@@ -589,8 -576,6 +576,8 @@@ handle_signal(unsigned long sig, struc
         */
        block_sigmask(ka, sig);
  
 +      tracehook_signal_handler(sig, info, ka, regs, 0);
 +
        return 0;
  }
  
@@@ -610,15 -595,6 +597,6 @@@ static void do_signal(struct pt_regs *r
        siginfo_t info;
        int signr;
  
-       /*
-        * We want the common case to go fast, which
-        * is why we may in certain cases get here from
-        * kernel mode. Just return without doing anything
-        * if so.
-        */
-       if (!user_mode(regs))
-               return;
        /*
         * If we were from a system call, check for system call restarting...
         */
                case -ERESTARTNOHAND:
                case -ERESTARTSYS:
                case -ERESTARTNOINTR:
+               case -ERESTART_RESTARTBLOCK:
                        regs->ARM_r0 = regs->ARM_ORIG_r0;
                        regs->ARM_pc = restart_addr;
                        break;
-               case -ERESTART_RESTARTBLOCK:
-                       regs->ARM_r0 = -EINTR;
-                       break;
                }
        }
  
-       if (try_to_freeze())
-               goto no_signal;
        /*
         * Get the signal to deliver.  When running under ptrace, at this
         * point the debugger may change all our registers ...
                 * debugger has chosen to restart at a different PC.
                 */
                if (regs->ARM_pc == restart_addr) {
-                       if (retval == -ERESTARTNOHAND
+                       if (retval == -ERESTARTNOHAND ||
+                           retval == -ERESTART_RESTARTBLOCK
                            || (retval == -ERESTARTSYS
                                && !(ka.sa.sa_flags & SA_RESTART))) {
                                regs->ARM_r0 = -EINTR;
                                regs->ARM_pc = continue_addr;
                        }
+                       clear_thread_flag(TIF_SYSCALL_RESTARTSYS);
                }
  
                if (test_thread_flag(TIF_RESTORE_SIGMASK))
                return;
        }
  
-  no_signal:
        if (syscall) {
                /*
                 * Handle restarting a different system call.  As above,
                 * ignore the restart.
                 */
                if (retval == -ERESTART_RESTARTBLOCK
-                   && regs->ARM_pc == continue_addr) {
-                       if (thumb_mode(regs)) {
-                               regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE;
-                               regs->ARM_pc -= 2;
-                       } else {
- #if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT)
-                               regs->ARM_r7 = __NR_restart_syscall;
-                               regs->ARM_pc -= 4;
- #else
-                               u32 __user *usp;
-                               regs->ARM_sp -= 4;
-                               usp = (u32 __user *)regs->ARM_sp;
-                               if (put_user(regs->ARM_pc, usp) == 0) {
-                                       regs->ARM_pc = KERN_RESTART_CODE;
-                               } else {
-                                       regs->ARM_sp += 4;
-                                       force_sigsegv(0, current);
-                               }
- #endif
-                       }
-               }
-               /* If there's no signal to deliver, we just put the saved sigmask
-                * back.
-                */
-               if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-                       clear_thread_flag(TIF_RESTORE_SIGMASK);
-                       sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-               }
+                   && regs->ARM_pc == restart_addr)
+                       set_thread_flag(TIF_SYSCALL_RESTARTSYS);
        }
+       /* If there's no signal to deliver, we just put the saved sigmask
+        * back.
+        */
+       if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
+               set_current_blocked(&current->saved_sigmask);
  }
  
  asmlinkage void
diff --combined arch/arm/kernel/traps.c
index 3647170e9a16ba3aa8838218ed99e74dbc5b7c59,5aef330e9c5480be0a281819ba0016acb9d2b5a8..4928d89758f4ce0dea767acdf9fcf2299dff7833
@@@ -479,14 -479,14 +479,14 @@@ static int bad_syscall(int n, struct pt
        return regs->ARM_r0;
  }
  
 -static inline void
 +static inline int
  do_cache_op(unsigned long start, unsigned long end, int flags)
  {
        struct mm_struct *mm = current->active_mm;
        struct vm_area_struct *vma;
  
        if (end < start || flags)
 -              return;
 +              return -EINVAL;
  
        down_read(&mm->mmap_sem);
        vma = find_vma(mm, start);
                if (end > vma->vm_end)
                        end = vma->vm_end;
  
 -              flush_cache_user_range(vma, start, end);
 +              up_read(&mm->mmap_sem);
 +              return flush_cache_user_range(start, end);
        }
        up_read(&mm->mmap_sem);
 +      return -EINVAL;
  }
  
  /*
@@@ -546,7 -544,8 +546,7 @@@ asmlinkage int arm_syscall(int no, stru
         * the specified region).
         */
        case NR(cacheflush):
 -              do_cache_op(regs->ARM_r0, regs->ARM_r1, regs->ARM_r2);
 -              return 0;
 +              return do_cache_op(regs->ARM_r0, regs->ARM_r1, regs->ARM_r2);
  
        case NR(usr26):
                if (!(elf_hwcap & HWCAP_26BIT))
@@@ -820,8 -819,6 +820,6 @@@ void __init early_trap_init(void *vecto
         */
        memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE),
               sigreturn_codes, sizeof(sigreturn_codes));
-       memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE),
-              syscall_restart_code, sizeof(syscall_restart_code));
  
        flush_icache_range(vectors, vectors + PAGE_SIZE);
        modify_domain(DOMAIN_USER, DOMAIN_CLIENT);