aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/entry/common.c
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@kernel.org>2015-10-05 17:48:20 -0700
committerIngo Molnar <mingo@kernel.org>2015-10-09 09:41:12 +0200
commitc68ca6787bdd6d2df37cf950135aa11e71af358a (patch)
treee4c1c92be7f20cd4dc4b74ed605d494bc4154afb /arch/x86/entry/common.c
parentx86/entry: Force inlining of 32-bit syscall code (diff)
downloadlinux-dev-c68ca6787bdd6d2df37cf950135aa11e71af358a.tar.xz
linux-dev-c68ca6787bdd6d2df37cf950135aa11e71af358a.zip
x86/entry: Micro-optimize compat fast syscall arg fetch
We're following a 32-bit pointer, and the uaccess code isn't smart enough to figure out that the access_ok() check isn't needed. This saves about three cycles on a cache-hot fast syscall. 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/bdff034e2f23c5eb974c760cf494cb5bddce8f29.1444091585.git.luto@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/entry/common.c')
-rw-r--r--arch/x86/entry/common.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index d5eee851071c..08a945d7915e 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -394,8 +394,20 @@ __visible long do_fast_syscall_32(struct pt_regs *regs)
* 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)) {
+ if (
+#ifdef CONFIG_X86_64
+ /*
+ * Micro-optimization: the pointer we're following is explicitly
+ * 32 bits, so it can't be out of range.
+ */
+ __get_user(*(u32 *)&regs->cx,
+ (u32 __user __force *)(unsigned long)(u32)regs->sp)
+#else
+ get_user(*(u32 *)&regs->cx,
+ (u32 __user __force *)(unsigned long)(u32)regs->sp)
+#endif
+ ) {
+
/* User code screwed up. */
local_irq_disable();
regs->ax = -EFAULT;