]> Pileus Git - ~andy/linux/blobdiff - arch/x86/kvm/x86.c
Merge branch 'omap-clock-for-next' of git://git.pwsan.com/linux-2.6 into devel
[~andy/linux] / arch / x86 / kvm / x86.c
index 96413f4e33bab473c551a1f23f2234b108bd97c1..249540f985132f79922736a8dd49f8febeb71bdf 100644 (file)
@@ -1441,8 +1441,7 @@ static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
                return -ENXIO;
        vcpu_load(vcpu);
 
-       set_bit(irq->irq, vcpu->arch.irq_pending);
-       set_bit(irq->irq / BITS_PER_LONG, &vcpu->arch.irq_summary);
+       kvm_queue_interrupt(vcpu, irq->irq, false);
 
        vcpu_put(vcpu);
 
@@ -3143,7 +3142,10 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu)
        if (!kvm_x86_ops->update_cr8_intercept)
                return;
 
-       max_irr = kvm_lapic_find_highest_irr(vcpu);
+       if (!vcpu->arch.apic->vapic_addr)
+               max_irr = kvm_lapic_find_highest_irr(vcpu);
+       else
+               max_irr = -1;
 
        if (max_irr != -1)
                max_irr >>= 4;
@@ -3153,8 +3155,11 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu)
        kvm_x86_ops->update_cr8_intercept(vcpu, tpr, max_irr);
 }
 
-static void inject_irq(struct kvm_vcpu *vcpu)
+static void inject_pending_irq(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
+       if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
+               kvm_x86_ops->set_interrupt_shadow(vcpu, 0);
+
        /* try to reinject previous events if any */
        if (vcpu->arch.nmi_injected) {
                kvm_x86_ops->set_nmi(vcpu);
@@ -3162,7 +3167,7 @@ static void inject_irq(struct kvm_vcpu *vcpu)
        }
 
        if (vcpu->arch.interrupt.pending) {
-               kvm_x86_ops->set_irq(vcpu, vcpu->arch.interrupt.nr);
+               kvm_x86_ops->set_irq(vcpu);
                return;
        }
 
@@ -3175,32 +3180,18 @@ static void inject_irq(struct kvm_vcpu *vcpu)
                }
        } else if (kvm_cpu_has_interrupt(vcpu)) {
                if (kvm_x86_ops->interrupt_allowed(vcpu)) {
-                       kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
-                       kvm_x86_ops->set_irq(vcpu, vcpu->arch.interrupt.nr);
+                       kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu),
+                                           false);
+                       kvm_x86_ops->set_irq(vcpu);
                }
        }
 }
 
-static void inject_pending_irq(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
-{
-       bool req_int_win = !irqchip_in_kernel(vcpu->kvm) &&
-               kvm_run->request_interrupt_window;
-
-       if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
-               kvm_x86_ops->set_interrupt_shadow(vcpu, 0);
-
-       inject_irq(vcpu);
-
-       /* enable NMI/IRQ window open exits if needed */
-       if (vcpu->arch.nmi_pending)
-               kvm_x86_ops->enable_nmi_window(vcpu);
-       else if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
-               kvm_x86_ops->enable_irq_window(vcpu);
-}
-
 static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        int r;
+       bool req_int_win = !irqchip_in_kernel(vcpu->kvm) &&
+               kvm_run->request_interrupt_window;
 
        if (vcpu->requests)
                if (test_and_clear_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
@@ -3254,11 +3245,15 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        else
                inject_pending_irq(vcpu, kvm_run);
 
+       /* enable NMI/IRQ window open exits if needed */
+       if (vcpu->arch.nmi_pending)
+               kvm_x86_ops->enable_nmi_window(vcpu);
+       else if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
+               kvm_x86_ops->enable_irq_window(vcpu);
+
        if (kvm_lapic_enabled(vcpu)) {
-               if (!vcpu->arch.apic->vapic_addr)
-                       update_cr8_intercept(vcpu);
-               else
-                       kvm_lapic_sync_to_vapic(vcpu);
+               update_cr8_intercept(vcpu);
+               kvm_lapic_sync_to_vapic(vcpu);
        }
 
        up_read(&vcpu->kvm->slots_lock);
@@ -3583,14 +3578,9 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
        sregs->efer = vcpu->arch.shadow_efer;
        sregs->apic_base = kvm_get_apic_base(vcpu);
 
-       if (irqchip_in_kernel(vcpu->kvm))
-               memset(sregs->interrupt_bitmap, 0,
-                      sizeof sregs->interrupt_bitmap);
-       else
-               memcpy(sregs->interrupt_bitmap, vcpu->arch.irq_pending,
-                      sizeof sregs->interrupt_bitmap);
+       memset(sregs->interrupt_bitmap, 0, sizeof sregs->interrupt_bitmap);
 
-       if (vcpu->arch.interrupt.pending)
+       if (vcpu->arch.interrupt.pending && !vcpu->arch.interrupt.soft)
                set_bit(vcpu->arch.interrupt.nr,
                        (unsigned long *)sregs->interrupt_bitmap);
 
@@ -4058,7 +4048,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
                                  struct kvm_sregs *sregs)
 {
        int mmu_reset_needed = 0;
-       int i, pending_vec, max_bits;
+       int pending_vec, max_bits;
        struct descriptor_table dt;
 
        vcpu_load(vcpu);
@@ -4100,24 +4090,14 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        if (mmu_reset_needed)
                kvm_mmu_reset_context(vcpu);
 
-       if (!irqchip_in_kernel(vcpu->kvm)) {
-               memcpy(vcpu->arch.irq_pending, sregs->interrupt_bitmap,
-                      sizeof vcpu->arch.irq_pending);
-               vcpu->arch.irq_summary = 0;
-               for (i = 0; i < ARRAY_SIZE(vcpu->arch.irq_pending); ++i)
-                       if (vcpu->arch.irq_pending[i])
-                               __set_bit(i, &vcpu->arch.irq_summary);
-       } else {
-               max_bits = (sizeof sregs->interrupt_bitmap) << 3;
-               pending_vec = find_first_bit(
-                       (const unsigned long *)sregs->interrupt_bitmap,
-                       max_bits);
-               /* Only pending external irq is handled here */
-               if (pending_vec < max_bits) {
-                       kvm_queue_interrupt(vcpu, pending_vec);
-                       pr_debug("Set back pending irq %d\n", pending_vec);
-               }
-               kvm_pic_clear_isr_ack(vcpu->kvm);
+       max_bits = (sizeof sregs->interrupt_bitmap) << 3;
+       pending_vec = find_first_bit(
+               (const unsigned long *)sregs->interrupt_bitmap, max_bits);
+       if (pending_vec < max_bits) {
+               kvm_queue_interrupt(vcpu, pending_vec, false);
+               pr_debug("Set back pending irq %d\n", pending_vec);
+               if (irqchip_in_kernel(vcpu->kvm))
+                       kvm_pic_clear_isr_ack(vcpu->kvm);
        }
 
        kvm_set_segment(vcpu, &sregs->cs, VCPU_SREG_CS);