KVM: Remove kvm_push_irq()
[safe/jmp/linux-2.6] / arch / x86 / kvm / i8254.c
index c743509..4d6f0d2 100644 (file)
@@ -35,7 +35,7 @@
 #include "i8254.h"
 
 #ifndef CONFIG_X86_64
-#define mod_64(x, y) ((x) - (y) * div64_64(x, y))
+#define mod_64(x, y) ((x) - (y) * div64_u64(x, y))
 #else
 #define mod_64(x, y) ((x) % (y))
 #endif
@@ -60,8 +60,8 @@ static u64 muldiv64(u64 a, u32 b, u32 c)
        rl = (u64)u.l.low * (u64)b;
        rh = (u64)u.l.high * (u64)b;
        rh += (rl >> 32);
-       res.l.high = div64_64(rh, c);
-       res.l.low = div64_64(((mod_64(rh, c) << 32) + (rl & 0xffffffff)), c);
+       res.l.high = div64_u64(rh, c);
+       res.l.low = div64_u64(((mod_64(rh, c) << 32) + (rl & 0xffffffff)), c);
        return res.ll;
 }
 
@@ -91,13 +91,44 @@ static void pit_set_gate(struct kvm *kvm, int channel, u32 val)
        c->gate = val;
 }
 
-int pit_get_gate(struct kvm *kvm, int channel)
+static int pit_get_gate(struct kvm *kvm, int channel)
 {
        WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
 
        return kvm->arch.vpit->pit_state.channels[channel].gate;
 }
 
+static s64 __kpit_elapsed(struct kvm *kvm)
+{
+       s64 elapsed;
+       ktime_t remaining;
+       struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state;
+
+       /*
+        * The Counter does not stop when it reaches zero. In
+        * Modes 0, 1, 4, and 5 the Counter ``wraps around'' to
+        * the highest count, either FFFF hex for binary counting
+        * or 9999 for BCD counting, and continues counting.
+        * Modes 2 and 3 are periodic; the Counter reloads
+        * itself with the initial count and continues counting
+        * from there.
+        */
+       remaining = hrtimer_expires_remaining(&ps->pit_timer.timer);
+       elapsed = ps->pit_timer.period - ktime_to_ns(remaining);
+       elapsed = mod_64(elapsed, ps->pit_timer.period);
+
+       return elapsed;
+}
+
+static s64 kpit_elapsed(struct kvm *kvm, struct kvm_kpit_channel_state *c,
+                       int channel)
+{
+       if (channel == 0)
+               return __kpit_elapsed(kvm);
+
+       return ktime_to_ns(ktime_sub(ktime_get(), c->count_load_time));
+}
+
 static int pit_get_count(struct kvm *kvm, int channel)
 {
        struct kvm_kpit_channel_state *c =
@@ -107,7 +138,7 @@ static int pit_get_count(struct kvm *kvm, int channel)
 
        WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
 
-       t = ktime_to_ns(ktime_sub(ktime_get(), c->count_load_time));
+       t = kpit_elapsed(kvm, c, channel);
        d = muldiv64(t, KVM_PIT_FREQ, NSEC_PER_SEC);
 
        switch (c->mode) {
@@ -137,7 +168,7 @@ static int pit_get_out(struct kvm *kvm, int channel)
 
        WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
 
-       t = ktime_to_ns(ktime_sub(ktime_get(), c->count_load_time));
+       t = kpit_elapsed(kvm, c, channel);
        d = muldiv64(t, KVM_PIT_FREQ, NSEC_PER_SEC);
 
        switch (c->mode) {
@@ -193,48 +224,59 @@ static void pit_latch_status(struct kvm *kvm, int channel)
        }
 }
 
-int __pit_timer_fn(struct kvm_kpit_state *ps)
+int pit_has_pending_timer(struct kvm_vcpu *vcpu)
 {
-       struct kvm_vcpu *vcpu0 = ps->pit->kvm->vcpus[0];
-       struct kvm_kpit_timer *pt = &ps->pit_timer;
-
-       atomic_inc(&pt->pending);
-       smp_mb__after_atomic_inc();
-       /* FIXME: handle case where the guest is in guest mode */
-       if (vcpu0 && waitqueue_active(&vcpu0->wq)) {
-               vcpu0->arch.mp_state = VCPU_MP_STATE_RUNNABLE;
-               wake_up_interruptible(&vcpu0->wq);
-       }
-
-       pt->timer.expires = ktime_add_ns(pt->timer.expires, pt->period);
-       pt->scheduled = ktime_to_ns(pt->timer.expires);
+       struct kvm_pit *pit = vcpu->kvm->arch.vpit;
 
-       return (pt->period == 0 ? 0 : 1);
+       if (pit && vcpu->vcpu_id == 0 && pit->pit_state.irq_ack)
+               return atomic_read(&pit->pit_state.pit_timer.pending);
+       return 0;
 }
 
-static enum hrtimer_restart pit_timer_fn(struct hrtimer *data)
+static void kvm_pit_ack_irq(struct kvm_irq_ack_notifier *kian)
 {
-       struct kvm_kpit_state *ps;
-       int restart_timer = 0;
+       struct kvm_kpit_state *ps = container_of(kian, struct kvm_kpit_state,
+                                                irq_ack_notifier);
+       spin_lock(&ps->inject_lock);
+       if (atomic_dec_return(&ps->pit_timer.pending) < 0)
+               atomic_inc(&ps->pit_timer.pending);
+       ps->irq_ack = 1;
+       spin_unlock(&ps->inject_lock);
+}
 
-       ps = container_of(data, struct kvm_kpit_state, pit_timer.timer);
+void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu)
+{
+       struct kvm_pit *pit = vcpu->kvm->arch.vpit;
+       struct hrtimer *timer;
 
-       restart_timer = __pit_timer_fn(ps);
+       if (vcpu->vcpu_id != 0 || !pit)
+               return;
 
-       if (restart_timer)
-               return HRTIMER_RESTART;
-       else
-               return HRTIMER_NORESTART;
+       timer = &pit->pit_state.pit_timer.timer;
+       if (hrtimer_cancel(timer))
+               hrtimer_start_expires(timer, HRTIMER_MODE_ABS);
 }
 
-static void destroy_pit_timer(struct kvm_kpit_timer *pt)
+static void destroy_pit_timer(struct kvm_timer *pt)
 {
        pr_debug("pit: execute del timer!\n");
        hrtimer_cancel(&pt->timer);
 }
 
-static void create_pit_timer(struct kvm_kpit_timer *pt, u32 val, int is_period)
+static bool kpit_is_periodic(struct kvm_timer *ktimer)
+{
+       struct kvm_kpit_state *ps = container_of(ktimer, struct kvm_kpit_state,
+                                                pit_timer);
+       return ps->is_periodic;
+}
+
+static struct kvm_timer_ops kpit_ops = {
+       .is_periodic = kpit_is_periodic,
+};
+
+static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period)
 {
+       struct kvm_timer *pt = &ps->pit_timer;
        s64 interval;
 
        interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ);
@@ -243,9 +285,16 @@ static void create_pit_timer(struct kvm_kpit_timer *pt, u32 val, int is_period)
 
        /* TODO The new value only affected after the retriggered */
        hrtimer_cancel(&pt->timer);
-       pt->period = (is_period == 0) ? 0 : interval;
-       pt->timer.function = pit_timer_fn;
+       pt->period = interval;
+       ps->is_periodic = is_period;
+
+       pt->timer.function = kvm_timer_fn;
+       pt->t_ops = &kpit_ops;
+       pt->kvm = ps->pit->kvm;
+       pt->vcpu_id = 0;
+
        atomic_set(&pt->pending, 0);
+       ps->irq_ack = 1;
 
        hrtimer_start(&pt->timer, ktime_add_ns(ktime_get(), interval),
                      HRTIMER_MODE_ABS);
@@ -260,34 +309,44 @@ static void pit_load_count(struct kvm *kvm, int channel, u32 val)
        pr_debug("pit: load_count val is %d, channel is %d\n", val, channel);
 
        /*
-        * Though spec said the state of 8254 is undefined after power-up,
-        * seems some tricky OS like Windows XP depends on IRQ0 interrupt
-        * when booting up.
-        * So here setting initialize rate for it, and not a specific number
+        * The largest possible initial count is 0; this is equivalent
+        * to 216 for binary counting and 104 for BCD counting.
         */
        if (val == 0)
                val = 0x10000;
 
-       ps->channels[channel].count_load_time = ktime_get();
        ps->channels[channel].count = val;
 
-       if (channel != 0)
+       if (channel != 0) {
+               ps->channels[channel].count_load_time = ktime_get();
                return;
+       }
 
        /* Two types of timer
         * mode 1 is one shot, mode 2 is period, otherwise del timer */
        switch (ps->channels[0].mode) {
+       case 0:
        case 1:
-               create_pit_timer(&ps->pit_timer, val, 0);
+        /* FIXME: enhance mode 4 precision */
+       case 4:
+               create_pit_timer(ps, val, 0);
                break;
        case 2:
-               create_pit_timer(&ps->pit_timer, val, 1);
+       case 3:
+               create_pit_timer(ps, val, 1);
                break;
        default:
                destroy_pit_timer(&ps->pit_timer);
        }
 }
 
+void kvm_pit_load_count(struct kvm *kvm, int channel, u32 val)
+{
+       mutex_lock(&kvm->arch.vpit->pit_state.lock);
+       pit_load_count(kvm, channel, val);
+       mutex_unlock(&kvm->arch.vpit->pit_state.lock);
+}
+
 static void pit_ioport_write(struct kvm_io_device *this,
                             gpa_t addr, int len, const void *data)
 {
@@ -425,7 +484,8 @@ static void pit_ioport_read(struct kvm_io_device *this,
        mutex_unlock(&pit_state->lock);
 }
 
-static int pit_in_range(struct kvm_io_device *this, gpa_t addr)
+static int pit_in_range(struct kvm_io_device *this, gpa_t addr,
+                       int len, int is_write)
 {
        return ((addr >= KVM_PIT_BASE_ADDRESS) &&
                (addr < KVM_PIT_BASE_ADDRESS + KVM_PIT_MEM_LENGTH));
@@ -466,24 +526,58 @@ static void speaker_ioport_read(struct kvm_io_device *this,
        mutex_unlock(&pit_state->lock);
 }
 
-static int speaker_in_range(struct kvm_io_device *this, gpa_t addr)
+static int speaker_in_range(struct kvm_io_device *this, gpa_t addr,
+                           int len, int is_write)
 {
        return (addr == KVM_SPEAKER_BASE_ADDRESS);
 }
 
-struct kvm_pit *kvm_create_pit(struct kvm *kvm)
+void kvm_pit_reset(struct kvm_pit *pit)
 {
        int i;
+       struct kvm_kpit_channel_state *c;
+
+       mutex_lock(&pit->pit_state.lock);
+       for (i = 0; i < 3; i++) {
+               c = &pit->pit_state.channels[i];
+               c->mode = 0xff;
+               c->gate = (i != 2);
+               pit_load_count(pit->kvm, i, 0);
+       }
+       mutex_unlock(&pit->pit_state.lock);
+
+       atomic_set(&pit->pit_state.pit_timer.pending, 0);
+       pit->pit_state.irq_ack = 1;
+}
+
+static void pit_mask_notifer(struct kvm_irq_mask_notifier *kimn, bool mask)
+{
+       struct kvm_pit *pit = container_of(kimn, struct kvm_pit, mask_notifier);
+
+       if (!mask) {
+               atomic_set(&pit->pit_state.pit_timer.pending, 0);
+               pit->pit_state.irq_ack = 1;
+       }
+}
+
+struct kvm_pit *kvm_create_pit(struct kvm *kvm)
+{
        struct kvm_pit *pit;
        struct kvm_kpit_state *pit_state;
-       struct kvm_kpit_channel_state *c;
 
        pit = kzalloc(sizeof(struct kvm_pit), GFP_KERNEL);
        if (!pit)
                return NULL;
 
+       pit->irq_source_id = kvm_request_irq_source_id(kvm);
+       if (pit->irq_source_id < 0) {
+               kfree(pit);
+               return NULL;
+       }
+
        mutex_init(&pit->pit_state.lock);
        mutex_lock(&pit->pit_state.lock);
+       spin_lock_init(&pit->pit_state.inject_lock);
 
        /* Initialize PIO device */
        pit->dev.read = pit_ioport_read;
@@ -505,17 +599,16 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm)
        pit_state->pit = pit;
        hrtimer_init(&pit_state->pit_timer.timer,
                     CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
-       atomic_set(&pit_state->pit_timer.pending, 0);
-       for (i = 0; i < 3; i++) {
-               c = &pit_state->channels[i];
-               c->mode = 0xff;
-               c->gate = (i != 2);
-               pit_load_count(kvm, i, 0);
-       }
-
+       pit_state->irq_ack_notifier.gsi = 0;
+       pit_state->irq_ack_notifier.irq_acked = kvm_pit_ack_irq;
+       kvm_register_irq_ack_notifier(kvm, &pit_state->irq_ack_notifier);
+       pit_state->pit_timer.reinject = true;
        mutex_unlock(&pit->pit_state.lock);
 
-       pit->pit_state.inject_pending = 1;
+       kvm_pit_reset(pit);
+
+       pit->mask_notifier.func = pit_mask_notifer;
+       kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
 
        return pit;
 }
@@ -525,22 +618,42 @@ void kvm_free_pit(struct kvm *kvm)
        struct hrtimer *timer;
 
        if (kvm->arch.vpit) {
+               kvm_unregister_irq_mask_notifier(kvm, 0,
+                                              &kvm->arch.vpit->mask_notifier);
                mutex_lock(&kvm->arch.vpit->pit_state.lock);
                timer = &kvm->arch.vpit->pit_state.pit_timer.timer;
                hrtimer_cancel(timer);
+               kvm_free_irq_source_id(kvm, kvm->arch.vpit->irq_source_id);
                mutex_unlock(&kvm->arch.vpit->pit_state.lock);
                kfree(kvm->arch.vpit);
        }
 }
 
-void __inject_pit_timer_intr(struct kvm *kvm)
+static void __inject_pit_timer_intr(struct kvm *kvm)
 {
+       struct kvm_vcpu *vcpu;
+       int i;
+
        mutex_lock(&kvm->lock);
-       kvm_ioapic_set_irq(kvm->arch.vioapic, 0, 1);
-       kvm_ioapic_set_irq(kvm->arch.vioapic, 0, 0);
-       kvm_pic_set_irq(pic_irqchip(kvm), 0, 1);
-       kvm_pic_set_irq(pic_irqchip(kvm), 0, 0);
+       kvm_set_irq(kvm, kvm->arch.vpit->irq_source_id, 0, 1);
+       kvm_set_irq(kvm, kvm->arch.vpit->irq_source_id, 0, 0);
        mutex_unlock(&kvm->lock);
+
+       /*
+        * Provides NMI watchdog support via Virtual Wire mode.
+        * The route is: PIT -> PIC -> LVT0 in NMI mode.
+        *
+        * Note: Our Virtual Wire implementation is simplified, only
+        * propagating PIT interrupts to all VCPUs when they have set
+        * LVT0 to NMI delivery. Other PIC interrupts are just sent to
+        * VCPU0, and only if its LVT0 is in EXTINT mode.
+        */
+       if (kvm->arch.vapics_in_nmi_mode > 0)
+               for (i = 0; i < KVM_MAX_VCPUS; ++i) {
+                       vcpu = kvm->vcpus[i];
+                       if (vcpu)
+                               kvm_apic_nmi_wd_deliver(vcpu);
+               }
 }
 
 void kvm_inject_pit_timer_irqs(struct kvm_vcpu *vcpu)
@@ -550,37 +663,19 @@ void kvm_inject_pit_timer_irqs(struct kvm_vcpu *vcpu)
        struct kvm_kpit_state *ps;
 
        if (vcpu && pit) {
+               int inject = 0;
                ps = &pit->pit_state;
 
-               /* Try to inject pending interrupts when:
-                * 1. Pending exists
-                * 2. Last interrupt was accepted or waited for too long time*/
-               if (atomic_read(&ps->pit_timer.pending) &&
-                   (ps->inject_pending ||
-                   (jiffies - ps->last_injected_time
-                               >= KVM_MAX_PIT_INTR_INTERVAL))) {
-                       ps->inject_pending = 0;
-                       __inject_pit_timer_intr(kvm);
-                       ps->last_injected_time = jiffies;
-               }
-       }
-}
-
-void kvm_pit_timer_intr_post(struct kvm_vcpu *vcpu, int vec)
-{
-       struct kvm_arch *arch = &vcpu->kvm->arch;
-       struct kvm_kpit_state *ps;
-
-       if (vcpu && arch->vpit) {
-               ps = &arch->vpit->pit_state;
-               if (atomic_read(&ps->pit_timer.pending) &&
-               (((arch->vpic->pics[0].imr & 1) == 0 &&
-                 arch->vpic->pics[0].irq_base == vec) ||
-                 (arch->vioapic->redirtbl[0].fields.vector == vec &&
-                 arch->vioapic->redirtbl[0].fields.mask != 1))) {
-                       ps->inject_pending = 1;
-                       atomic_dec(&ps->pit_timer.pending);
-                       ps->channels[0].count_load_time = ktime_get();
+               /* Try to inject pending interrupts when
+                * last one has been acked.
+                */
+               spin_lock(&ps->inject_lock);
+               if (atomic_read(&ps->pit_timer.pending) && ps->irq_ack) {
+                       ps->irq_ack = 0;
+                       inject = 1;
                }
+               spin_unlock(&ps->inject_lock);
+               if (inject)
+                       __inject_pit_timer_intr(kvm);
        }
 }