Skip to content

Commit

Permalink
x86/entry: Add C code for fast system call entries
Browse files Browse the repository at this point in the history
This handles both SYSENTER and SYSCALL.  The asm glue will take
care of the differences.

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: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Link: http://lkml.kernel.org/r/6041a58a9b8ef6d2522ab4350deb1a1945eb563f.1444091585.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Andy Lutomirski authored and Ingo Molnar committed Oct 9, 2015
1 parent ee08c6b commit 710246d
Showing 1 changed file with 43 additions and 0 deletions.
43 changes: 43 additions & 0 deletions arch/x86/entry/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

#include <asm/desc.h>
#include <asm/traps.h>
#include <asm/vdso.h>
#include <asm/uaccess.h>

#define CREATE_TRACE_POINTS
#include <trace/events/syscalls.h>
Expand Down Expand Up @@ -360,4 +362,45 @@ __visible void do_int80_syscall_32(struct pt_regs *regs)

syscall_return_slowpath(regs);
}

__visible void do_fast_syscall_32(struct pt_regs *regs)
{
/*
* Called using the internal vDSO SYSENTER/SYSCALL32 calling
* convention. Adjust regs so it looks like we entered using int80.
*/

unsigned long landing_pad = (unsigned long)current->mm->context.vdso +
vdso_image_32.sym_int80_landing_pad;

/*
* SYSENTER loses EIP, and even SYSCALL32 needs us to skip forward
* so that 'regs->ip -= 2' lands back on an int $0x80 instruction.
* Fix it up.
*/
regs->ip = landing_pad;

/*
* Fetch ECX from where the vDSO stashed it.
*
* WARNING: We are in CONTEXT_USER and RCU isn't paying attention!
*/
local_irq_enable();
if (get_user(*(u32 *)&regs->cx,
(u32 __user __force *)(unsigned long)(u32)regs->sp)) {
/* User code screwed up. */
local_irq_disable();
regs->ax = -EFAULT;
#ifdef CONFIG_CONTEXT_TRACKING
enter_from_user_mode();
#endif
prepare_exit_to_usermode(regs);
return;
}
local_irq_disable();

/* Now this is just like a normal syscall. */
do_int80_syscall_32(regs);
return;
}
#endif

0 comments on commit 710246d

Please sign in to comment.