Example #1
0
/* Called with IRQs disabled. */
__visible void prepare_exit_to_usermode(struct pt_regs *regs)
{
    if (WARN_ON(!irqs_disabled()))
        local_irq_disable();

    /*
     * In order to return to user mode, we need to have IRQs off with
     * none of _TIF_SIGPENDING, _TIF_NOTIFY_RESUME, _TIF_USER_RETURN_NOTIFY,
     * _TIF_UPROBE, or _TIF_NEED_RESCHED set.  Several of these flags
     * can be set at any time on preemptable kernels if we have IRQs on,
     * so we need to loop.  Disabling preemption wouldn't help: doing the
     * work to clear some of the flags can sleep.
     */
    while (true) {
        u32 cached_flags =
            READ_ONCE(pt_regs_to_thread_info(regs)->flags);

        if (!(cached_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME |
                              _TIF_UPROBE | _TIF_NEED_RESCHED |
                              _TIF_USER_RETURN_NOTIFY)))
            break;

        /* We have work to do. */
        local_irq_enable();

        if (cached_flags & _TIF_NEED_RESCHED)
            schedule();

        if (cached_flags & _TIF_UPROBE)
            uprobe_notify_resume(regs);

        /* deal with pending signal delivery */
        if (cached_flags & _TIF_SIGPENDING)
            do_signal(regs);

        if (cached_flags & _TIF_NOTIFY_RESUME) {
            clear_thread_flag(TIF_NOTIFY_RESUME);
            tracehook_notify_resume(regs);
        }

        if (cached_flags & _TIF_USER_RETURN_NOTIFY)
            fire_user_return_notifiers();

        /* Disable IRQs and retry */
        local_irq_disable();
    }

    user_enter();
}
Example #2
0
static void exit_to_usermode_loop(struct pt_regs *regs, u32 cached_flags)
{
	/*
	 * In order to return to user mode, we need to have IRQs off with
	 * none of EXIT_TO_USERMODE_LOOP_FLAGS set.  Several of these flags
	 * can be set at any time on preemptible kernels if we have IRQs on,
	 * so we need to loop.  Disabling preemption wouldn't help: doing the
	 * work to clear some of the flags can sleep.
	 */
	while (true) {
		/* We have work to do. */
		local_irq_enable();

		if (cached_flags & _TIF_NEED_RESCHED)
			schedule();

		if (cached_flags & _TIF_UPROBE)
			uprobe_notify_resume(regs);

		if (cached_flags & _TIF_PATCH_PENDING)
			klp_update_patch_state(current);

		/* deal with pending signal delivery */
		if (cached_flags & _TIF_SIGPENDING)
			do_signal(regs);

		if (cached_flags & _TIF_NOTIFY_RESUME) {
			clear_thread_flag(TIF_NOTIFY_RESUME);
			tracehook_notify_resume(regs);
			rseq_handle_notify_resume(NULL, regs);
		}

		if (cached_flags & _TIF_USER_RETURN_NOTIFY)
			fire_user_return_notifiers();

		/* Disable IRQs and retry */
		local_irq_disable();

		cached_flags = READ_ONCE(current_thread_info()->flags);

		if (!(cached_flags & EXIT_TO_USERMODE_LOOP_FLAGS))
			break;
	}
}