Skip to content

Commit

Permalink
lguest, x86/entry/32: Fix handling of guest syscalls using interrupt …
Browse files Browse the repository at this point in the history
…gates

In a798f09 ("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 <[email protected]>
Cc: Andy Lutomirski <[email protected]>
Cc: Andy Lutomirski <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Brian Gerst <[email protected]>
Cc: Denys Vlasenko <[email protected]>
Cc: H. Peter Anvin <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Weisbecker <[email protected]>
Cc: x86\@kernel.org
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
rustyrussell authored and Ingo Molnar committed Apr 1, 2016
1 parent 6d92bc9 commit f87e043
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 2 deletions.
6 changes: 5 additions & 1 deletion drivers/lguest/interrupts_and_traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down
1 change: 1 addition & 0 deletions drivers/lguest/lg.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
6 changes: 5 additions & 1 deletion drivers/lguest/x86/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit f87e043

Please sign in to comment.