Example #1
0
/*
 * Called with IRQs on and fully valid regs.  Returns with IRQs off in a
 * state such that we can immediately switch to user mode.
 */
__visible inline void syscall_return_slowpath(struct pt_regs *regs)
{
	struct thread_info *ti = pt_regs_to_thread_info(regs);
	u32 cached_flags = READ_ONCE(ti->flags);

	CT_WARN_ON(ct_state() != CONTEXT_KERNEL);

	if (IS_ENABLED(CONFIG_PROVE_LOCKING) &&
	    WARN(irqs_disabled(), "syscall %ld left IRQs disabled", regs->orig_ax))
		local_irq_enable();

	/*
	 * First do one-time work.  If these work items are enabled, we
	 * want to run them exactly once per syscall exit with IRQs on.
	 */
	if (unlikely(cached_flags & SYSCALL_EXIT_WORK_FLAGS))
		syscall_slow_exit_work(regs, cached_flags);

#ifdef CONFIG_COMPAT
	/*
	 * Compat syscalls set TS_COMPAT.  Make sure we clear it before
	 * returning to user mode.
	 */
	ti->status &= ~TS_COMPAT;
#endif

	local_irq_disable();
	prepare_exit_to_usermode(regs);
}
Example #2
0
/*
 * Called with IRQs on and fully valid regs.  Returns with IRQs off in a
 * state such that we can immediately switch to user mode.
 */
__visible void syscall_return_slowpath(struct pt_regs *regs)
{
    struct thread_info *ti = pt_regs_to_thread_info(regs);
    u32 cached_flags = READ_ONCE(ti->flags);
    bool step;

    CT_WARN_ON(ct_state() != CONTEXT_KERNEL);

    if (WARN(irqs_disabled(), "syscall %ld left IRQs disabled",
             regs->orig_ax))
        local_irq_enable();

    /*
     * First do one-time work.  If these work items are enabled, we
     * want to run them exactly once per syscall exit with IRQs on.
     */
    if (cached_flags & (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT |
                        _TIF_SINGLESTEP | _TIF_SYSCALL_TRACEPOINT)) {
        audit_syscall_exit(regs);

        if (cached_flags & _TIF_SYSCALL_TRACEPOINT)
            trace_sys_exit(regs, regs->ax);

        /*
         * If TIF_SYSCALL_EMU is set, we only get here because of
         * TIF_SINGLESTEP (i.e. this is PTRACE_SYSEMU_SINGLESTEP).
         * We already reported this syscall instruction in
         * syscall_trace_enter().
         */
        step = unlikely(
                   (cached_flags & (_TIF_SINGLESTEP | _TIF_SYSCALL_EMU))
                   == _TIF_SINGLESTEP);
        if (step || cached_flags & _TIF_SYSCALL_TRACE)
            tracehook_report_syscall_exit(regs, step);
    }

#ifdef CONFIG_COMPAT
    /*
     * Compat syscalls set TS_COMPAT.  Make sure we clear it before
     * returning to user mode.
     */
    ti->status &= ~TS_COMPAT;
#endif

    local_irq_disable();
    prepare_exit_to_usermode(regs);
}
Example #3
0
/*
 * Called with IRQs on and fully valid regs.  Returns with IRQs off in a
 * state such that we can immediately switch to user mode.
 */
__visible inline void syscall_return_slowpath(struct pt_regs *regs)
{
	struct thread_info *ti = current_thread_info();
	u32 cached_flags = READ_ONCE(ti->flags);

	CT_WARN_ON(ct_state() != CONTEXT_KERNEL);

	if (IS_ENABLED(CONFIG_PROVE_LOCKING) &&
	    WARN(irqs_disabled(), "syscall %ld left IRQs disabled", regs->orig_ax))
		local_irq_enable();

	/*
	 * First do one-time work.  If these work items are enabled, we
	 * want to run them exactly once per syscall exit with IRQs on.
	 */
	if (unlikely(cached_flags & SYSCALL_EXIT_WORK_FLAGS))
		syscall_slow_exit_work(regs, cached_flags);

	local_irq_disable();
	prepare_exit_to_usermode(regs);
}
Example #4
0
/* Called on entry from user mode with IRQs off. */
__visible inline void enter_from_user_mode(void)
{
	CT_WARN_ON(ct_state() != CONTEXT_USER);
	user_exit_irqoff();
}