aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@kernel.org>2016-03-09 16:24:32 -0500
committerIngo Molnar <mingo@kernel.org>2016-03-10 04:53:26 -0500
commita798f091113ef4999277dbe0483d37d04fa35b2e (patch)
tree25a795b4f3da2670f6b507eecc2f0d54c9b1f741 /arch/x86
parentfda57b2267e12de014069b1596a5438cf76fc7c6 (diff)
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: 657c1eea0019 ("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>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/entry/common.c15
-rw-r--r--arch/x86/entry/entry_32.S8
-rw-r--r--arch/x86/entry/entry_64_compat.S2
-rw-r--r--arch/x86/kernel/traps.c2
4 files changed, 9 insertions, 18 deletions
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index 209ba334e90f..d69d1b6e6c31 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -371,14 +371,7 @@ __visible void do_syscall_64(struct pt_regs *regs)
371 * in workloads that use it, and it's usually called from 371 * in workloads that use it, and it's usually called from
372 * do_fast_syscall_32, so forcibly inline it to improve performance. 372 * do_fast_syscall_32, so forcibly inline it to improve performance.
373 */ 373 */
374#ifdef CONFIG_X86_32 374static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs)
375/* 32-bit kernels use a trap gate for INT80, and the asm code calls here. */
376__visible
377#else
378/* 64-bit kernels use do_syscall_32_irqs_off() instead. */
379static
380#endif
381__always_inline void do_syscall_32_irqs_on(struct pt_regs *regs)
382{ 375{
383 struct thread_info *ti = pt_regs_to_thread_info(regs); 376 struct thread_info *ti = pt_regs_to_thread_info(regs);
384 unsigned int nr = (unsigned int)regs->orig_ax; 377 unsigned int nr = (unsigned int)regs->orig_ax;
@@ -413,14 +406,12 @@ __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs)
413 syscall_return_slowpath(regs); 406 syscall_return_slowpath(regs);
414} 407}
415 408
416#ifdef CONFIG_X86_64 409/* Handles int $0x80 */
417/* Handles INT80 on 64-bit kernels */ 410__visible void do_int80_syscall_32(struct pt_regs *regs)
418__visible void do_syscall_32_irqs_off(struct pt_regs *regs)
419{ 411{
420 local_irq_enable(); 412 local_irq_enable();
421 do_syscall_32_irqs_on(regs); 413 do_syscall_32_irqs_on(regs);
422} 414}
423#endif
424 415
425/* Returns 0 to return using IRET or 1 to return using SYSEXIT/SYSRETL. */ 416/* Returns 0 to return using IRET or 1 to return using SYSEXIT/SYSRETL. */
426__visible long do_fast_syscall_32(struct pt_regs *regs) 417__visible long do_fast_syscall_32(struct pt_regs *regs)
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index 286efa342091..10868aa734dc 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -463,13 +463,13 @@ ENTRY(entry_INT80_32)
463 SAVE_ALL pt_regs_ax=$-ENOSYS /* save rest */ 463 SAVE_ALL pt_regs_ax=$-ENOSYS /* save rest */
464 464
465 /* 465 /*
466 * User mode is traced as though IRQs are on. Unlike the 64-bit 466 * User mode is traced as though IRQs are on, and the interrupt gate
467 * case, INT80 is a trap gate on 32-bit kernels, so interrupts 467 * turned them off.
468 * are already on (unless user code is messing around with iopl).
469 */ 468 */
469 TRACE_IRQS_OFF
470 470
471 movl %esp, %eax 471 movl %esp, %eax
472 call do_syscall_32_irqs_on 472 call do_int80_syscall_32
473.Lsyscall_32_done: 473.Lsyscall_32_done:
474 474
475restore_all: 475restore_all:
diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S
index efe0fe3f76bc..847f2f0c31e5 100644
--- a/arch/x86/entry/entry_64_compat.S
+++ b/arch/x86/entry/entry_64_compat.S
@@ -336,7 +336,7 @@ ENTRY(entry_INT80_compat)
336 TRACE_IRQS_OFF 336 TRACE_IRQS_OFF
337 337
338 movq %rsp, %rdi 338 movq %rsp, %rdi
339 call do_syscall_32_irqs_off 339 call do_int80_syscall_32
340.Lsyscall_32_done: 340.Lsyscall_32_done:
341 341
342 /* Go back to user mode. */ 342 /* Go back to user mode. */
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 49e2e775f507..5fae2d840e64 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -912,7 +912,7 @@ void __init trap_init(void)
912#endif 912#endif
913 913
914#ifdef CONFIG_X86_32 914#ifdef CONFIG_X86_32
915 set_system_trap_gate(IA32_SYSCALL_VECTOR, entry_INT80_32); 915 set_system_intr_gate(IA32_SYSCALL_VECTOR, entry_INT80_32);
916 set_bit(IA32_SYSCALL_VECTOR, used_vectors); 916 set_bit(IA32_SYSCALL_VECTOR, used_vectors);
917#endif 917#endif
918 918