diff options
author | Andy Lutomirski <luto@kernel.org> | 2015-10-05 17:48:15 -0700 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-10-09 09:41:10 +0200 |
commit | 5f310f739b4cc343f3f087681e41bbc2f0ce902d (patch) | |
tree | 97260d2bbfbcd9abd277148c3e8b7e4c49e6c163 /arch/x86/entry/common.c | |
parent | 150ac78d63afb96360dab448b7b4d33c98c8266c (diff) | |
download | lwn-5f310f739b4cc343f3f087681e41bbc2f0ce902d.tar.gz lwn-5f310f739b4cc343f3f087681e41bbc2f0ce902d.zip |
x86/entry/32: Re-implement SYSENTER using the new C path
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/5b99659e8be70f3dd10cd8970a5c90293d9ad9a7.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.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index 88dc5ba14d47..0ed023d6a983 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -363,7 +363,7 @@ __visible void do_int80_syscall_32(struct pt_regs *regs) syscall_return_slowpath(regs); } -/* Returns 0 to return using IRET or 1 to return using SYSRETL. */ +/* Returns 0 to return using IRET or 1 to return using SYSEXIT/SYSRETL. */ __visible long do_fast_syscall_32(struct pt_regs *regs) { /* @@ -417,7 +417,20 @@ __visible long do_fast_syscall_32(struct pt_regs *regs) regs->ip == landing_pad && (regs->flags & (X86_EFLAGS_RF | X86_EFLAGS_TF)) == 0; #else - return 0; + /* + * Opportunistic SYSEXIT: if possible, try to return using SYSEXIT. + * + * Unlike 64-bit opportunistic SYSRET, we can't check that CX == IP, + * because the ECX fixup above will ensure that this is essentially + * never the case. + * + * We don't allow syscalls at all from VM86 mode, but we still + * need to check VM, because we might be returning from sys_vm86. + */ + return static_cpu_has(X86_FEATURE_SEP) && + regs->cs == __USER_CS && regs->ss == __USER_DS && + regs->ip == landing_pad && + (regs->flags & (X86_EFLAGS_RF | X86_EFLAGS_TF | X86_EFLAGS_VM)) == 0; #endif } #endif |