static void pit_cal_count(struct hvm_virpit *vpit)
{
- u64 nsec_delta = (unsigned int)((NOW() - vpit->inject_point));
+ u64 nsec_delta = (unsigned int)((NOW() - vpit->count_point));
+ nsec_delta += vpit->count_advance;
if (nsec_delta > vpit->period)
HVM_DBG_LOG(DBG_LEVEL_1,
"HVM_PIT: long time has passed from last injection!");
} else {
vpit->pending_intr_nr--;
}
- vpit->inject_point = NOW();
+ vpit->count_advance = 0;
+ vpit->count_point = NOW();
vpit->last_pit_gtime += vpit->period_cycles;
svm_set_guest_time(v, vpit->last_pit_gtime);
if ( vpit->first_injected && !v->domain->arch.hvm_domain.guest_time ) {
v->domain->arch.hvm_domain.guest_time = svm_get_guest_time(v);
+ vpit->count_advance += (NOW() - vpit->count_point);
stop_timer(&(vpit->pit_timer));
}
}
if ( vpit->first_injected ) {
if ( v->domain->arch.hvm_domain.guest_time ) {
svm_set_guest_time(v, v->domain->arch.hvm_domain.guest_time);
+ vpit->count_point = NOW();
v->domain->arch.hvm_domain.guest_time = 0;
}
pickup_deactive_ticks(vpit);
} else {
vpit->pending_intr_nr--;
}
- vpit->inject_point = NOW();
+ vpit->count_advance = 0;
+ vpit->count_point = NOW();
vpit->last_pit_gtime += vpit->period_cycles;
set_guest_time(v, vpit->last_pit_gtime);
/* pick up the elapsed PIT ticks and re-enable pit_timer */
if ( vpit->first_injected ) {
if ( v->domain->arch.hvm_domain.guest_time ) {
+ vpit->count_point = NOW();
set_guest_time(v, v->domain->arch.hvm_domain.guest_time);
v->domain->arch.hvm_domain.guest_time = 0;
}
if ( vpit->first_injected && !v->domain->arch.hvm_domain.guest_time ) {
v->domain->arch.hvm_domain.guest_time = get_guest_time(v);
+ vpit->count_advance += (NOW() - vpit->count_point);
stop_timer(&(vpit->pit_timer));
}
}
struct hvm_virpit {
/* for simulation of counter 0 in mode 2 */
u64 period_cycles; /* pit frequency in cpu cycles */
- s_time_t inject_point; /* the time inject virt intr */
+ s_time_t count_advance; /* accumulated count advance since last fire */
+ s_time_t count_point; /* last point accumulating count advance */
s_time_t scheduled; /* scheduled timer interrupt */
struct timer pit_timer; /* periodic timer for mode 2*/
unsigned int channel; /* the pit channel, counter 0~2 */