timer.c 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. #include <linux/kvm_host.h>
  2. #include <linux/kvm.h>
  3. #include <linux/hrtimer.h>
  4. #include <asm/atomic.h>
  5. #include "kvm_timer.h"
  6. static int __kvm_timer_fn(struct kvm_vcpu *vcpu, struct kvm_timer *ktimer)
  7. {
  8. int restart_timer = 0;
  9. wait_queue_head_t *q = &vcpu->wq;
  10. /*
  11. * There is a race window between reading and incrementing, but we do
  12. * not care about potentially loosing timer events in the !reinject
  13. * case anyway. Note: KVM_REQ_PENDING_TIMER is implicitly checked
  14. * in vcpu_enter_guest.
  15. */
  16. if (ktimer->reinject || !atomic_read(&ktimer->pending)) {
  17. atomic_inc(&ktimer->pending);
  18. /* FIXME: this code should not know anything about vcpus */
  19. set_bit(KVM_REQ_PENDING_TIMER, &vcpu->requests);
  20. }
  21. if (waitqueue_active(q))
  22. wake_up_interruptible(q);
  23. if (ktimer->t_ops->is_periodic(ktimer)) {
  24. hrtimer_add_expires_ns(&ktimer->timer, ktimer->period);
  25. restart_timer = 1;
  26. }
  27. return restart_timer;
  28. }
  29. enum hrtimer_restart kvm_timer_fn(struct hrtimer *data)
  30. {
  31. int restart_timer;
  32. struct kvm_vcpu *vcpu;
  33. struct kvm_timer *ktimer = container_of(data, struct kvm_timer, timer);
  34. vcpu = ktimer->vcpu;
  35. if (!vcpu)
  36. return HRTIMER_NORESTART;
  37. restart_timer = __kvm_timer_fn(vcpu, ktimer);
  38. if (restart_timer)
  39. return HRTIMER_RESTART;
  40. else
  41. return HRTIMER_NORESTART;
  42. }