x86: get rid of calling do_notify_resume() when returning to kernel mode
If we end up calling do_notify_resume() with !user_mode(refs), it does nothing (do_signal() explicitly bails out and we can't get there with TIF_NOTIFY_RESUME in such situations). Then we jump to resume_userspace_sig, which rechecks the same thing and bails out to resume_kernel, thus breaking the loop. It's easier and cheaper to check *before* calling do_notify_resume() and bail out to resume_kernel immediately. And kill the check in do_signal()... Note that on amd64 we can't get there with !user_mode() at all - asm glue takes care of that. Acked-and-reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
29bf5dd895
commit
44fbbb3dc6
|
@ -316,7 +316,6 @@ ret_from_exception:
|
||||||
preempt_stop(CLBR_ANY)
|
preempt_stop(CLBR_ANY)
|
||||||
ret_from_intr:
|
ret_from_intr:
|
||||||
GET_THREAD_INFO(%ebp)
|
GET_THREAD_INFO(%ebp)
|
||||||
resume_userspace_sig:
|
|
||||||
#ifdef CONFIG_VM86
|
#ifdef CONFIG_VM86
|
||||||
movl PT_EFLAGS(%esp), %eax # mix EFLAGS and CS
|
movl PT_EFLAGS(%esp), %eax # mix EFLAGS and CS
|
||||||
movb PT_CS(%esp), %al
|
movb PT_CS(%esp), %al
|
||||||
|
@ -615,9 +614,13 @@ work_notifysig: # deal with pending signals and
|
||||||
# vm86-space
|
# vm86-space
|
||||||
TRACE_IRQS_ON
|
TRACE_IRQS_ON
|
||||||
ENABLE_INTERRUPTS(CLBR_NONE)
|
ENABLE_INTERRUPTS(CLBR_NONE)
|
||||||
|
movb PT_CS(%esp), %bl
|
||||||
|
andb $SEGMENT_RPL_MASK, %bl
|
||||||
|
cmpb $USER_RPL, %bl
|
||||||
|
jb resume_kernel
|
||||||
xorl %edx, %edx
|
xorl %edx, %edx
|
||||||
call do_notify_resume
|
call do_notify_resume
|
||||||
jmp resume_userspace_sig
|
jmp resume_userspace
|
||||||
|
|
||||||
ALIGN
|
ALIGN
|
||||||
work_notifysig_v86:
|
work_notifysig_v86:
|
||||||
|
@ -630,9 +633,13 @@ work_notifysig_v86:
|
||||||
#endif
|
#endif
|
||||||
TRACE_IRQS_ON
|
TRACE_IRQS_ON
|
||||||
ENABLE_INTERRUPTS(CLBR_NONE)
|
ENABLE_INTERRUPTS(CLBR_NONE)
|
||||||
|
movb PT_CS(%esp), %bl
|
||||||
|
andb $SEGMENT_RPL_MASK, %bl
|
||||||
|
cmpb $USER_RPL, %bl
|
||||||
|
jb resume_kernel
|
||||||
xorl %edx, %edx
|
xorl %edx, %edx
|
||||||
call do_notify_resume
|
call do_notify_resume
|
||||||
jmp resume_userspace_sig
|
jmp resume_userspace
|
||||||
END(work_pending)
|
END(work_pending)
|
||||||
|
|
||||||
# perform syscall exit tracing
|
# perform syscall exit tracing
|
||||||
|
|
|
@ -737,16 +737,6 @@ static void do_signal(struct pt_regs *regs)
|
||||||
siginfo_t info;
|
siginfo_t info;
|
||||||
int signr;
|
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.
|
|
||||||
* X86_32: vm86 regs switched out by assembly code before reaching
|
|
||||||
* here, so testing against kernel CS suffices.
|
|
||||||
*/
|
|
||||||
if (!user_mode(regs))
|
|
||||||
return;
|
|
||||||
|
|
||||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||||
if (signr > 0) {
|
if (signr > 0) {
|
||||||
/* Whee! Actually deliver the signal. */
|
/* Whee! Actually deliver the signal. */
|
||||||
|
|
Loading…
Reference in New Issue