2010-05-23 19:37:00 +04:00
/*
* Kernel - based Virtual Machine driver for Linux
*
* This module enables machines with Intel VT - x extensions to run virtual
* machines without emulation or binary translation .
*
* timer support
*
2010-10-06 16:23:22 +04:00
* Copyright 2010 Red Hat , Inc . and / or its affiliates .
2010-05-23 19:37:00 +04:00
*
* This work is licensed under the terms of the GNU GPL , version 2. See
* the COPYING file in the top - level directory .
*/
2009-02-23 16:57:41 +03:00
# include <linux/kvm_host.h>
# include <linux/kvm.h>
# include <linux/hrtimer.h>
# include <asm/atomic.h>
# include "kvm_timer.h"
static int __kvm_timer_fn ( struct kvm_vcpu * vcpu , struct kvm_timer * ktimer )
{
int restart_timer = 0 ;
wait_queue_head_t * q = & vcpu - > wq ;
2009-06-09 17:37:01 +04:00
/*
* There is a race window between reading and incrementing , but we do
* not care about potentially loosing timer events in the ! reinject
2010-03-23 20:15:53 +03:00
* case anyway . Note : KVM_REQ_PENDING_TIMER is implicitly checked
* in vcpu_enter_guest .
2009-06-09 17:37:01 +04:00
*/
if ( ktimer - > reinject | | ! atomic_read ( & ktimer - > pending ) ) {
2009-06-09 17:37:03 +04:00
atomic_inc ( & ktimer - > pending ) ;
2009-06-09 17:37:01 +04:00
/* FIXME: this code should not know anything about vcpus */
2010-05-10 13:34:53 +04:00
kvm_make_request ( KVM_REQ_PENDING_TIMER , vcpu ) ;
2009-06-09 17:37:01 +04:00
}
2009-02-23 16:57:41 +03:00
if ( waitqueue_active ( q ) )
wake_up_interruptible ( q ) ;
if ( ktimer - > t_ops - > is_periodic ( ktimer ) ) {
hrtimer_add_expires_ns ( & ktimer - > timer , ktimer - > period ) ;
restart_timer = 1 ;
}
return restart_timer ;
}
enum hrtimer_restart kvm_timer_fn ( struct hrtimer * data )
{
int restart_timer ;
struct kvm_vcpu * vcpu ;
struct kvm_timer * ktimer = container_of ( data , struct kvm_timer , timer ) ;
2009-06-09 16:56:27 +04:00
vcpu = ktimer - > vcpu ;
2009-02-23 16:57:41 +03:00
if ( ! vcpu )
return HRTIMER_NORESTART ;
restart_timer = __kvm_timer_fn ( vcpu , ktimer ) ;
if ( restart_timer )
return HRTIMER_RESTART ;
else
return HRTIMER_NORESTART ;
}