Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758749AbcDAHlV (ORCPT ); Fri, 1 Apr 2016 03:41:21 -0400 Received: from terminus.zytor.com ([198.137.202.10]:34006 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758554AbcDAHlT (ORCPT ); Fri, 1 Apr 2016 03:41:19 -0400 Date: Fri, 1 Apr 2016 00:40:03 -0700 From: tip-bot for Rusty Russell Message-ID: Cc: bp@alien8.de, luto@amacapital.net, hpa@zytor.com, rusty@rustcorp.com.au, peterz@infradead.org, torvalds@linux-foundation.org, fweisbec@gmail.com, luto@kernel.org, linux-kernel@vger.kernel.org, dvlasenk@redhat.com, tglx@linutronix.de, mingo@kernel.org, brgerst@gmail.com Reply-To: rusty@rustcorp.com.au, torvalds@linux-foundation.org, fweisbec@gmail.com, peterz@infradead.org, dvlasenk@redhat.com, linux-kernel@vger.kernel.org, luto@kernel.org, brgerst@gmail.com, mingo@kernel.org, tglx@linutronix.de, bp@alien8.de, luto@amacapital.net, hpa@zytor.com In-Reply-To: <87fuv685kl.fsf@rustcorp.com.au> References: <87fuv685kl.fsf@rustcorp.com.au> To: linux-tip-commits@vger.kernel.org Subject: [tip:x86/urgent] lguest, x86/entry/32: Fix handling of guest syscalls using interrupt gates Git-Commit-ID: f87e0434a3bedeb5e4d75d96d9f3ad424dae6b33 X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3990 Lines: 98 Commit-ID: f87e0434a3bedeb5e4d75d96d9f3ad424dae6b33 Gitweb: http://git.kernel.org/tip/f87e0434a3bedeb5e4d75d96d9f3ad424dae6b33 Author: Rusty Russell AuthorDate: Fri, 1 Apr 2016 12:15:46 +1030 Committer: Ingo Molnar CommitDate: Fri, 1 Apr 2016 08:58:13 +0200 lguest, x86/entry/32: Fix handling of guest syscalls using interrupt gates In a798f091113e ("x86/entry/32: Change INT80 to be an interrupt gate") Andy broke lguest. This is because lguest had special code to allow the 0x80 trap gate go straight into the guest itself; interrupts gates (without more work, as mentioned in the file's comments) bounce via the hypervisor. His change made them go via the hypervisor, but as it's in the range of normal hardware interrupts, they were not directed through to the guest at all. Turns out the guest userspace isn't very effective if syscalls are all noops. I haven't ripped out all the now-useless trap-direct-to-guest-kernel code yet, since it will still be needed if someone decides to update this optimization. Signed-off-by: Rusty Russell Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Weisbecker Cc: x86\@kernel.org Link: http://lkml.kernel.org/r/87fuv685kl.fsf@rustcorp.com.au Signed-off-by: Ingo Molnar --- drivers/lguest/interrupts_and_traps.c | 6 +++++- drivers/lguest/lg.h | 1 + drivers/lguest/x86/core.c | 6 +++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c index eb934b0..67392b6 100644 --- a/drivers/lguest/interrupts_and_traps.c +++ b/drivers/lguest/interrupts_and_traps.c @@ -331,7 +331,7 @@ void set_interrupt(struct lg_cpu *cpu, unsigned int irq) * Actually now I think of it, it's possible that Ron *is* half the Plan 9 * userbase. Oh well. */ -static bool could_be_syscall(unsigned int num) +bool could_be_syscall(unsigned int num) { /* Normal Linux IA32_SYSCALL_VECTOR or reserved vector? */ return num == IA32_SYSCALL_VECTOR || num == syscall_vector; @@ -416,6 +416,10 @@ bool deliver_trap(struct lg_cpu *cpu, unsigned int num) * * This routine indicates if a particular trap number could be delivered * directly. + * + * Unfortunately, Linux 4.6 started using an interrupt gate instead of a + * trap gate for syscalls, so this trick is ineffective. See Mastery for + * how we could do this anyway... */ static bool direct_trap(unsigned int num) { diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h index ac8ad04..69b3814 100644 --- a/drivers/lguest/lg.h +++ b/drivers/lguest/lg.h @@ -167,6 +167,7 @@ void guest_set_clockevent(struct lg_cpu *cpu, unsigned long delta); bool send_notify_to_eventfd(struct lg_cpu *cpu); void init_clockdev(struct lg_cpu *cpu); bool check_syscall_vector(struct lguest *lg); +bool could_be_syscall(unsigned int num); int init_interrupts(void); void free_interrupts(void); diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 6a4cd77..adc162c 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -429,8 +429,12 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu) return; break; case 32 ... 255: + /* This might be a syscall. */ + if (could_be_syscall(cpu->regs->trapnum)) + break; + /* - * These values mean a real interrupt occurred, in which case + * Other values mean a real interrupt occurred, in which case * the Host handler has already been run. We just do a * friendly check if another process should now be run, then * return to run the Guest again.