Merge tag 'core-entry-notify-signal' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / kernel / entry / common.c
index 42eff11..33bb5f9 100644 (file)
@@ -60,6 +60,9 @@ static long syscall_trace_enter(struct pt_regs *regs, long syscall,
                        return ret;
        }
 
+       /* Either of the above might have changed the syscall number */
+       syscall = syscall_get_nr(current, regs);
+
        if (unlikely(ti_work & _TIF_SYSCALL_TRACEPOINT))
                trace_sys_enter(regs, syscall);
 
@@ -68,22 +71,45 @@ static long syscall_trace_enter(struct pt_regs *regs, long syscall,
        return ret ? : syscall;
 }
 
-noinstr long syscall_enter_from_user_mode(struct pt_regs *regs, long syscall)
+static __always_inline long
+__syscall_enter_from_user_work(struct pt_regs *regs, long syscall)
 {
        unsigned long ti_work;
 
-       enter_from_user_mode(regs);
-       instrumentation_begin();
-
-       local_irq_enable();
        ti_work = READ_ONCE(current_thread_info()->flags);
        if (ti_work & SYSCALL_ENTER_WORK)
                syscall = syscall_trace_enter(regs, syscall, ti_work);
-       instrumentation_end();
 
        return syscall;
 }
 
+long syscall_enter_from_user_mode_work(struct pt_regs *regs, long syscall)
+{
+       return __syscall_enter_from_user_work(regs, syscall);
+}
+
+noinstr long syscall_enter_from_user_mode(struct pt_regs *regs, long syscall)
+{
+       long ret;
+
+       enter_from_user_mode(regs);
+
+       instrumentation_begin();
+       local_irq_enable();
+       ret = __syscall_enter_from_user_work(regs, syscall);
+       instrumentation_end();
+
+       return ret;
+}
+
+noinstr void syscall_enter_from_user_mode_prepare(struct pt_regs *regs)
+{
+       enter_from_user_mode(regs);
+       instrumentation_begin();
+       local_irq_enable();
+       instrumentation_end();
+}
+
 /**
  * exit_to_user_mode - Fixup state when exiting to user mode
  *
@@ -143,7 +169,6 @@ static unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
                        handle_signal_work(regs, ti_work);
 
                if (ti_work & _TIF_NOTIFY_RESUME) {
-                       clear_thread_flag(TIF_NOTIFY_RESUME);
                        tracehook_notify_resume(regs);
                        rseq_handle_notify_resume(NULL, regs);
                }
@@ -190,7 +215,7 @@ static inline bool report_single_step(unsigned long ti_work)
 /*
  * If TIF_SYSCALL_EMU is set, then the only reason to report is when
  * TIF_SINGLESTEP is set (i.e. PTRACE_SYSEMU_SINGLESTEP).  This syscall
- * instruction has been already reported in syscall_enter_from_usermode().
+ * instruction has been already reported in syscall_enter_from_user_mode().
  */
 #define SYSEMU_STEP    (_TIF_SINGLESTEP | _TIF_SYSCALL_EMU)
 
@@ -286,7 +311,7 @@ noinstr irqentry_state_t irqentry_enter(struct pt_regs *regs)
         * terminate a grace period, if and only if the timer interrupt is
         * not nested into another interrupt.
         *
-        * Checking for __rcu_is_watching() here would prevent the nesting
+        * Checking for rcu_is_watching() here would prevent the nesting
         * interrupt to invoke rcu_irq_enter(). If that nested interrupt is
         * the tick then rcu_flavor_sched_clock_irq() would wrongfully
         * assume that it is the first interupt and eventually claim
@@ -320,10 +345,10 @@ noinstr irqentry_state_t irqentry_enter(struct pt_regs *regs)
         * already contains a warning when RCU is not watching, so no point
         * in having another one here.
         */
+       lockdep_hardirqs_off(CALLER_ADDR0);
        instrumentation_begin();
        rcu_irq_enter_check_tick();
-       /* Use the combo lockdep/tracing function */
-       trace_hardirqs_off();
+       trace_hardirqs_off_finish();
        instrumentation_end();
 
        return ret;