KVM: Use kvm_arch_interrupt_allowed() instead of checking interrupt_window_open directly
[safe/jmp/linux-2.6] / drivers / lguest / interrupts_and_traps.c
index 0414ddf..6e99adb 100644 (file)
@@ -34,7 +34,7 @@ static int idt_type(u32 lo, u32 hi)
 }
 
 /* An IDT entry can't be used unless the "present" bit is set. */
-static int idt_present(u32 lo, u32 hi)
+static bool idt_present(u32 lo, u32 hi)
 {
        return (hi & 0x8000);
 }
@@ -60,7 +60,8 @@ static void push_guest_stack(struct lg_cpu *cpu, unsigned long *gstack, u32 val)
  * We set up the stack just like the CPU does for a real interrupt, so it's
  * identical for the Guest (and the standard "iret" instruction will undo
  * it). */
-static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, int has_err)
+static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi,
+                               bool has_err)
 {
        unsigned long gstack, origstack;
        u32 eflags, ss, irq_enable;
@@ -184,7 +185,7 @@ void maybe_do_interrupt(struct lg_cpu *cpu)
                /* set_guest_interrupt() takes the interrupt descriptor and a
                 * flag to say whether this interrupt pushes an error code onto
                 * the stack as well: virtual interrupts never do. */
-               set_guest_interrupt(cpu, idt->a, idt->b, 0);
+               set_guest_interrupt(cpu, idt->a, idt->b, false);
        }
 
        /* Every time we deliver an interrupt, we update the timestamp in the
@@ -222,11 +223,16 @@ bool check_syscall_vector(struct lguest *lg)
 int init_interrupts(void)
 {
        /* If they want some strange system call vector, reserve it now */
-       if (syscall_vector != SYSCALL_VECTOR
-           && test_and_set_bit(syscall_vector, used_vectors)) {
-               printk("lg: couldn't reserve syscall %u\n", syscall_vector);
-               return -EBUSY;
+       if (syscall_vector != SYSCALL_VECTOR) {
+               if (test_bit(syscall_vector, used_vectors) ||
+                   vector_used_by_percpu_irq(syscall_vector)) {
+                       printk(KERN_ERR "lg: couldn't reserve syscall %u\n",
+                                syscall_vector);
+                       return -EBUSY;
+               }
+               set_bit(syscall_vector, used_vectors);
        }
+
        return 0;
 }
 
@@ -239,26 +245,26 @@ void free_interrupts(void)
 /*H:220 Now we've got the routines to deliver interrupts, delivering traps like
  * page fault is easy.  The only trick is that Intel decided that some traps
  * should have error codes: */
-static int has_err(unsigned int trap)
+static bool has_err(unsigned int trap)
 {
        return (trap == 8 || (trap >= 10 && trap <= 14) || trap == 17);
 }
 
 /* deliver_trap() returns true if it could deliver the trap. */
-int deliver_trap(struct lg_cpu *cpu, unsigned int num)
+bool deliver_trap(struct lg_cpu *cpu, unsigned int num)
 {
        /* Trap numbers are always 8 bit, but we set an impossible trap number
         * for traps inside the Switcher, so check that here. */
        if (num >= ARRAY_SIZE(cpu->arch.idt))
-               return 0;
+               return false;
 
        /* Early on the Guest hasn't set the IDT entries (or maybe it put a
         * bogus one in): if we fail here, the Guest will be killed. */
        if (!idt_present(cpu->arch.idt[num].a, cpu->arch.idt[num].b))
-               return 0;
+               return false;
        set_guest_interrupt(cpu, cpu->arch.idt[num].a,
                            cpu->arch.idt[num].b, has_err(num));
-       return 1;
+       return true;
 }
 
 /*H:250 Here's the hard part: returning to the Host every time a trap happens
@@ -274,18 +280,19 @@ int deliver_trap(struct lg_cpu *cpu, unsigned int num)
  *
  * This routine indicates if a particular trap number could be delivered
  * directly. */
-static int direct_trap(unsigned int num)
+static bool direct_trap(unsigned int num)
 {
        /* Hardware interrupts don't go to the Guest at all (except system
         * call). */
        if (num >= FIRST_EXTERNAL_VECTOR && !could_be_syscall(num))
-               return 0;
+               return false;
 
        /* The Host needs to see page faults (for shadow paging and to save the
         * fault address), general protection faults (in/out emulation) and
-        * device not available (TS handling), and of course, the hypercall
-        * trap. */
-       return num != 14 && num != 13 && num != 7 && num != LGUEST_TRAP_ENTRY;
+        * device not available (TS handling), invalid opcode fault (kvm hcall),
+        * and of course, the hypercall trap. */
+       return num != 14 && num != 13 && num != 7 &&
+                       num != 6 && num != LGUEST_TRAP_ENTRY;
 }
 /*:*/
 
@@ -406,7 +413,8 @@ void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int num, u32 lo, u32 hi)
  * deliver_trap() to bounce it back into the Guest. */
 static void default_idt_entry(struct desc_struct *idt,
                              int trap,
-                             const unsigned long handler)
+                             const unsigned long handler,
+                             const struct desc_struct *base)
 {
        /* A present interrupt gate. */
        u32 flags = 0x8e00;
@@ -415,6 +423,10 @@ static void default_idt_entry(struct desc_struct *idt,
         * the Guest to use the "int" instruction to trigger it. */
        if (trap == LGUEST_TRAP_ENTRY)
                flags |= (GUEST_PL << 13);
+       else if (base)
+               /* Copy priv. level from what Guest asked for.  This allows
+                * debug (int 3) traps from Guest userspace, for example. */
+               flags |= (base->b & 0x6000);
 
        /* Now pack it into the IDT entry in its weird format. */
        idt->a = (LGUEST_CS<<16) | (handler&0x0000FFFF);
@@ -428,7 +440,7 @@ void setup_default_idt_entries(struct lguest_ro_state *state,
        unsigned int i;
 
        for (i = 0; i < ARRAY_SIZE(state->guest_idt); i++)
-               default_idt_entry(&state->guest_idt[i], i, def[i]);
+               default_idt_entry(&state->guest_idt[i], i, def[i], NULL);
 }
 
 /*H:240 We don't use the IDT entries in the "struct lguest" directly, instead
@@ -442,6 +454,8 @@ void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt,
        /* We can simply copy the direct traps, otherwise we use the default
         * ones in the Switcher: they will return to the Host. */
        for (i = 0; i < ARRAY_SIZE(cpu->arch.idt); i++) {
+               const struct desc_struct *gidt = &cpu->arch.idt[i];
+
                /* If no Guest can ever override this trap, leave it alone. */
                if (!direct_trap(i))
                        continue;
@@ -449,12 +463,15 @@ void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt,
                /* Only trap gates (type 15) can go direct to the Guest.
                 * Interrupt gates (type 14) disable interrupts as they are
                 * entered, which we never let the Guest do.  Not present
-                * entries (type 0x0) also can't go direct, of course. */
-               if (idt_type(cpu->arch.idt[i].a, cpu->arch.idt[i].b) == 0xF)
-                       idt[i] = cpu->arch.idt[i];
+                * entries (type 0x0) also can't go direct, of course.
+                *
+                * If it can't go direct, we still need to copy the priv. level:
+                * they might want to give userspace access to a software
+                * interrupt. */
+               if (idt_type(gidt->a, gidt->b) == 0xF)
+                       idt[i] = *gidt;
                else
-                       /* Reset it to the default. */
-                       default_idt_entry(&idt[i], i, def[i]);
+                       default_idt_entry(&idt[i], i, def[i], gidt);
        }
 }