smp_call_function_single(ipi_pcpu, vcpu_kick_intr, vcpu, 0, 0);
 }
 
+void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu)
+{
+       kvm_inject_apic_timer_irqs(vcpu);
+       /* TODO: PIT, RTC etc. */
+}
+EXPORT_SYMBOL_GPL(kvm_inject_pending_timer_irqs);
+
+void kvm_timer_intr_post(struct kvm_vcpu *vcpu, int vec)
+{
+       kvm_apic_timer_intr_post(vcpu, vec);
+       /* TODO: PIT, RTC etc. */
+}
+EXPORT_SYMBOL_GPL(kvm_timer_intr_post);
 
 void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
 int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
 int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
+void kvm_apic_timer_intr_post(struct kvm_vcpu *vcpu, int vec);
+void kvm_timer_intr_post(struct kvm_vcpu *vcpu, int vec);
+void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu);
+void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu);
 
 #endif
 
 void kvm_vcpu_uninit(struct kvm_vcpu *vcpu)
 {
        kvm_mmu_destroy(vcpu);
+       if (vcpu->apic)
+               hrtimer_cancel(&vcpu->apic->timer.dev);
        kvm_free_apic(vcpu->apic);
        free_page((unsigned long)vcpu->pio_data);
        free_page((unsigned long)vcpu->run);
 
                             int vector, int level, int trig_mode)
 {
        int result = 0;
+       int orig_irr;
 
        switch (delivery_mode) {
        case APIC_DM_FIXED:
                if (unlikely(!apic_enabled(apic)))
                        break;
 
-               if (apic_test_and_set_irr(vector, apic) && trig_mode) {
+               orig_irr = apic_test_and_set_irr(vector, apic);
+               if (orig_irr && trig_mode) {
                        apic_debug("level trig mode repeatedly for vector %d",
                                   vector);
                        break;
 
                kvm_vcpu_kick(apic->vcpu);
 
-               result = 1;
+               result = (orig_irr == 0);
                break;
 
        case APIC_DM_REMRD:
  * timer interface
  *----------------------------------------------------------------------
  */
+
+/* TODO: make sure __apic_timer_fn runs in current pCPU */
 static int __apic_timer_fn(struct kvm_lapic *apic)
 {
-       u32 vector;
        int result = 0;
+       wait_queue_head_t *q = &apic->vcpu->wq;
 
-       if (unlikely(!apic_enabled(apic) ||
-                    !apic_lvt_enabled(apic, APIC_LVTT))) {
-               apic_debug("%s: time interrupt although apic is down\n",
-                          __FUNCTION__);
-               return 0;
-       }
-
-       vector = apic_lvt_vector(apic, APIC_LVTT);
-       apic->timer.last_update = apic->timer.dev.expires;
        atomic_inc(&apic->timer.pending);
-       __apic_accept_irq(apic, APIC_DM_FIXED, vector, 1, 0);
-
+       if (waitqueue_active(q))
+               wake_up_interruptible(q);
        if (apic_lvtt_period(apic)) {
-               u32 offset;
-               u32 tmict = apic_get_reg(apic, APIC_TMICT);
-
-               offset = APIC_BUS_CYCLE_NS * apic->timer.divide_count * tmict;
-
                result = 1;
                apic->timer.dev.expires = ktime_add_ns(
                                        apic->timer.dev.expires,
                                        apic->timer.period);
        }
-
        return result;
 }
 
+static int __inject_apic_timer_irq(struct kvm_lapic *apic)
+{
+       int vector;
+
+       vector = apic_lvt_vector(apic, APIC_LVTT);
+       return __apic_accept_irq(apic, APIC_DM_FIXED, vector, 1, 0);
+}
+
 static enum hrtimer_restart apic_timer_fn(struct hrtimer *data)
 {
        struct kvm_lapic *apic;
        return highest_irr;
 }
 
+void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu)
+{
+       struct kvm_lapic *apic = vcpu->apic;
+
+       if (apic && apic_lvt_enabled(apic, APIC_LVTT) &&
+               atomic_read(&apic->timer.pending) > 0) {
+               if (__inject_apic_timer_irq(apic))
+                       atomic_dec(&apic->timer.pending);
+       }
+}
+
+void kvm_apic_timer_intr_post(struct kvm_vcpu *vcpu, int vec)
+{
+       struct kvm_lapic *apic = vcpu->apic;
+
+       if (apic && apic_lvt_vector(apic, APIC_LVTT) == vec)
+               apic->timer.last_update = ktime_add_ns(
+                               apic->timer.last_update,
+                               apic->timer.period);
+}
+
 int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu)
 {
        int vector = kvm_apic_has_interrupt(vcpu);
 
 {
        struct vmcb *vmcb = svm->vmcb;
        int intr_vector = -1;
+       struct kvm_vcpu *vcpu = &svm->vcpu;
 
+       kvm_inject_pending_timer_irqs(vcpu);
        if ((vmcb->control.exit_int_info & SVM_EVTINJ_VALID) &&
            ((vmcb->control.exit_int_info & SVM_EVTINJ_TYPE_MASK) == 0)) {
                intr_vector = vmcb->control.exit_int_info &
        if (vmcb->control.int_ctl & V_IRQ_MASK)
                return;
 
-       if (!kvm_cpu_has_interrupt(&svm->vcpu))
+       if (!kvm_cpu_has_interrupt(vcpu))
                return;
 
        if (!(vmcb->save.rflags & X86_EFLAGS_IF) ||
                return;
        }
        /* Okay, we can deliver the interrupt: grab it and update PIC state. */
-       intr_vector = kvm_cpu_get_interrupt(&svm->vcpu);
+       intr_vector = kvm_cpu_get_interrupt(vcpu);
        svm_inject_irq(svm, intr_vector);
+       kvm_timer_intr_post(vcpu, intr_vector);
 }
 
 static void kvm_reput_irq(struct vcpu_svm *svm)
 
 {
        u32 idtv_info_field, intr_info_field;
        int has_ext_irq, interrupt_window_open;
+       int vector;
 
+       kvm_inject_pending_timer_irqs(vcpu);
        update_tpr_threshold(vcpu);
 
        has_ext_irq = kvm_cpu_has_interrupt(vcpu);
        interrupt_window_open =
                ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
                 (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0);
-       if (interrupt_window_open)
-               vmx_inject_irq(vcpu, kvm_cpu_get_interrupt(vcpu));
-       else
+       if (interrupt_window_open) {
+               vector = kvm_cpu_get_interrupt(vcpu);
+               vmx_inject_irq(vcpu, vector);
+               kvm_timer_intr_post(vcpu, vector);
+       } else
                enable_irq_window(vcpu);
 }