Skip to content

Commit f87e043

Browse files
rustyrussellIngo Molnar
authored andcommitted
lguest, x86/entry/32: Fix handling of guest syscalls using interrupt 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 <rusty@rustcorp.com.au> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Andy Lutomirski <luto@kernel.org> 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: Weisbecker <fweisbec@gmail.com> Cc: x86\@kernel.org Link: http://lkml.kernel.org/r/87fuv685kl.fsf@rustcorp.com.au Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent 6d92bc9 commit f87e043

File tree

3 files changed

+11
-2
lines changed

3 files changed

+11
-2
lines changed

drivers/lguest/interrupts_and_traps.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ void set_interrupt(struct lg_cpu *cpu, unsigned int irq)
331331
* Actually now I think of it, it's possible that Ron *is* half the Plan 9
332332
* userbase. Oh well.
333333
*/
334-
static bool could_be_syscall(unsigned int num)
334+
bool could_be_syscall(unsigned int num)
335335
{
336336
/* Normal Linux IA32_SYSCALL_VECTOR or reserved vector? */
337337
return num == IA32_SYSCALL_VECTOR || num == syscall_vector;
@@ -416,6 +416,10 @@ bool deliver_trap(struct lg_cpu *cpu, unsigned int num)
416416
*
417417
* This routine indicates if a particular trap number could be delivered
418418
* directly.
419+
*
420+
* Unfortunately, Linux 4.6 started using an interrupt gate instead of a
421+
* trap gate for syscalls, so this trick is ineffective. See Mastery for
422+
* how we could do this anyway...
419423
*/
420424
static bool direct_trap(unsigned int num)
421425
{

drivers/lguest/lg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ void guest_set_clockevent(struct lg_cpu *cpu, unsigned long delta);
167167
bool send_notify_to_eventfd(struct lg_cpu *cpu);
168168
void init_clockdev(struct lg_cpu *cpu);
169169
bool check_syscall_vector(struct lguest *lg);
170+
bool could_be_syscall(unsigned int num);
170171
int init_interrupts(void);
171172
void free_interrupts(void);
172173

drivers/lguest/x86/core.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,8 +429,12 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu)
429429
return;
430430
break;
431431
case 32 ... 255:
432+
/* This might be a syscall. */
433+
if (could_be_syscall(cpu->regs->trapnum))
434+
break;
435+
432436
/*
433-
* These values mean a real interrupt occurred, in which case
437+
* Other values mean a real interrupt occurred, in which case
434438
* the Host handler has already been run. We just do a
435439
* friendly check if another process should now be run, then
436440
* return to run the Guest again.

0 commit comments

Comments
 (0)