diff options
Diffstat (limited to 'arch/x86/kvm/i8254.c')
-rw-r--r-- | arch/x86/kvm/i8254.c | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c index 72bd275a9b5c..c13bb92d3157 100644 --- a/arch/x86/kvm/i8254.c +++ b/arch/x86/kvm/i8254.c | |||
@@ -201,6 +201,9 @@ static int __pit_timer_fn(struct kvm_kpit_state *ps) | |||
201 | if (!atomic_inc_and_test(&pt->pending)) | 201 | if (!atomic_inc_and_test(&pt->pending)) |
202 | set_bit(KVM_REQ_PENDING_TIMER, &vcpu0->requests); | 202 | set_bit(KVM_REQ_PENDING_TIMER, &vcpu0->requests); |
203 | 203 | ||
204 | if (!pt->reinject) | ||
205 | atomic_set(&pt->pending, 1); | ||
206 | |||
204 | if (vcpu0 && waitqueue_active(&vcpu0->wq)) | 207 | if (vcpu0 && waitqueue_active(&vcpu0->wq)) |
205 | wake_up_interruptible(&vcpu0->wq); | 208 | wake_up_interruptible(&vcpu0->wq); |
206 | 209 | ||
@@ -536,6 +539,16 @@ void kvm_pit_reset(struct kvm_pit *pit) | |||
536 | pit->pit_state.irq_ack = 1; | 539 | pit->pit_state.irq_ack = 1; |
537 | } | 540 | } |
538 | 541 | ||
542 | static void pit_mask_notifer(struct kvm_irq_mask_notifier *kimn, bool mask) | ||
543 | { | ||
544 | struct kvm_pit *pit = container_of(kimn, struct kvm_pit, mask_notifier); | ||
545 | |||
546 | if (!mask) { | ||
547 | atomic_set(&pit->pit_state.pit_timer.pending, 0); | ||
548 | pit->pit_state.irq_ack = 1; | ||
549 | } | ||
550 | } | ||
551 | |||
539 | struct kvm_pit *kvm_create_pit(struct kvm *kvm) | 552 | struct kvm_pit *kvm_create_pit(struct kvm *kvm) |
540 | { | 553 | { |
541 | struct kvm_pit *pit; | 554 | struct kvm_pit *pit; |
@@ -545,9 +558,7 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm) | |||
545 | if (!pit) | 558 | if (!pit) |
546 | return NULL; | 559 | return NULL; |
547 | 560 | ||
548 | mutex_lock(&kvm->lock); | ||
549 | pit->irq_source_id = kvm_request_irq_source_id(kvm); | 561 | pit->irq_source_id = kvm_request_irq_source_id(kvm); |
550 | mutex_unlock(&kvm->lock); | ||
551 | if (pit->irq_source_id < 0) { | 562 | if (pit->irq_source_id < 0) { |
552 | kfree(pit); | 563 | kfree(pit); |
553 | return NULL; | 564 | return NULL; |
@@ -580,10 +591,14 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm) | |||
580 | pit_state->irq_ack_notifier.gsi = 0; | 591 | pit_state->irq_ack_notifier.gsi = 0; |
581 | pit_state->irq_ack_notifier.irq_acked = kvm_pit_ack_irq; | 592 | pit_state->irq_ack_notifier.irq_acked = kvm_pit_ack_irq; |
582 | kvm_register_irq_ack_notifier(kvm, &pit_state->irq_ack_notifier); | 593 | kvm_register_irq_ack_notifier(kvm, &pit_state->irq_ack_notifier); |
594 | pit_state->pit_timer.reinject = true; | ||
583 | mutex_unlock(&pit->pit_state.lock); | 595 | mutex_unlock(&pit->pit_state.lock); |
584 | 596 | ||
585 | kvm_pit_reset(pit); | 597 | kvm_pit_reset(pit); |
586 | 598 | ||
599 | pit->mask_notifier.func = pit_mask_notifer; | ||
600 | kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier); | ||
601 | |||
587 | return pit; | 602 | return pit; |
588 | } | 603 | } |
589 | 604 | ||
@@ -592,6 +607,8 @@ void kvm_free_pit(struct kvm *kvm) | |||
592 | struct hrtimer *timer; | 607 | struct hrtimer *timer; |
593 | 608 | ||
594 | if (kvm->arch.vpit) { | 609 | if (kvm->arch.vpit) { |
610 | kvm_unregister_irq_mask_notifier(kvm, 0, | ||
611 | &kvm->arch.vpit->mask_notifier); | ||
595 | mutex_lock(&kvm->arch.vpit->pit_state.lock); | 612 | mutex_lock(&kvm->arch.vpit->pit_state.lock); |
596 | timer = &kvm->arch.vpit->pit_state.pit_timer.timer; | 613 | timer = &kvm->arch.vpit->pit_state.pit_timer.timer; |
597 | hrtimer_cancel(timer); | 614 | hrtimer_cancel(timer); |