x86/entry/32: Change INT80 to be an interrupt gate
We want all of the syscall entries to run with interrupts off so that
we can efficiently run context tracking before enabling interrupts.
This will regress int $0x80 performance on 32-bit kernels by a
couple of cycles. This shouldn't matter much -- int $0x80 is not a
fast path.
This effectively reverts:
657c1eea00
("x86/entry/32: Fix entry_INT80_32() to expect interrupts to be on")
... and fixes the same issue differently.
Signed-off-by: Andy Lutomirski <luto@kernel.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rik van Riel <riel@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/59b4f90c9ebfccd8c937305dbbbca680bc74b905.1457558566.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
fda57b2267
commit
a798f09111
|
@ -371,14 +371,7 @@ __visible void do_syscall_64(struct pt_regs *regs)
|
||||||
* in workloads that use it, and it's usually called from
|
* in workloads that use it, and it's usually called from
|
||||||
* do_fast_syscall_32, so forcibly inline it to improve performance.
|
* do_fast_syscall_32, so forcibly inline it to improve performance.
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_X86_32
|
static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs)
|
||||||
/* 32-bit kernels use a trap gate for INT80, and the asm code calls here. */
|
|
||||||
__visible
|
|
||||||
#else
|
|
||||||
/* 64-bit kernels use do_syscall_32_irqs_off() instead. */
|
|
||||||
static
|
|
||||||
#endif
|
|
||||||
__always_inline void do_syscall_32_irqs_on(struct pt_regs *regs)
|
|
||||||
{
|
{
|
||||||
struct thread_info *ti = pt_regs_to_thread_info(regs);
|
struct thread_info *ti = pt_regs_to_thread_info(regs);
|
||||||
unsigned int nr = (unsigned int)regs->orig_ax;
|
unsigned int nr = (unsigned int)regs->orig_ax;
|
||||||
|
@ -413,14 +406,12 @@ __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs)
|
||||||
syscall_return_slowpath(regs);
|
syscall_return_slowpath(regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
/* Handles int $0x80 */
|
||||||
/* Handles INT80 on 64-bit kernels */
|
__visible void do_int80_syscall_32(struct pt_regs *regs)
|
||||||
__visible void do_syscall_32_irqs_off(struct pt_regs *regs)
|
|
||||||
{
|
{
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
do_syscall_32_irqs_on(regs);
|
do_syscall_32_irqs_on(regs);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Returns 0 to return using IRET or 1 to return using SYSEXIT/SYSRETL. */
|
/* Returns 0 to return using IRET or 1 to return using SYSEXIT/SYSRETL. */
|
||||||
__visible long do_fast_syscall_32(struct pt_regs *regs)
|
__visible long do_fast_syscall_32(struct pt_regs *regs)
|
||||||
|
|
|
@ -463,13 +463,13 @@ ENTRY(entry_INT80_32)
|
||||||
SAVE_ALL pt_regs_ax=$-ENOSYS /* save rest */
|
SAVE_ALL pt_regs_ax=$-ENOSYS /* save rest */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* User mode is traced as though IRQs are on. Unlike the 64-bit
|
* User mode is traced as though IRQs are on, and the interrupt gate
|
||||||
* case, INT80 is a trap gate on 32-bit kernels, so interrupts
|
* turned them off.
|
||||||
* are already on (unless user code is messing around with iopl).
|
|
||||||
*/
|
*/
|
||||||
|
TRACE_IRQS_OFF
|
||||||
|
|
||||||
movl %esp, %eax
|
movl %esp, %eax
|
||||||
call do_syscall_32_irqs_on
|
call do_int80_syscall_32
|
||||||
.Lsyscall_32_done:
|
.Lsyscall_32_done:
|
||||||
|
|
||||||
restore_all:
|
restore_all:
|
||||||
|
|
|
@ -336,7 +336,7 @@ ENTRY(entry_INT80_compat)
|
||||||
TRACE_IRQS_OFF
|
TRACE_IRQS_OFF
|
||||||
|
|
||||||
movq %rsp, %rdi
|
movq %rsp, %rdi
|
||||||
call do_syscall_32_irqs_off
|
call do_int80_syscall_32
|
||||||
.Lsyscall_32_done:
|
.Lsyscall_32_done:
|
||||||
|
|
||||||
/* Go back to user mode. */
|
/* Go back to user mode. */
|
||||||
|
|
|
@ -912,7 +912,7 @@ void __init trap_init(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
set_system_trap_gate(IA32_SYSCALL_VECTOR, entry_INT80_32);
|
set_system_intr_gate(IA32_SYSCALL_VECTOR, entry_INT80_32);
|
||||||
set_bit(IA32_SYSCALL_VECTOR, used_vectors);
|
set_bit(IA32_SYSCALL_VECTOR, used_vectors);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue