break;
case HVM_PARAM_TIMER_MODE:
rc = -EINVAL;
- if ( (a.value != HVMPTM_delay_for_missed_ticks) &&
- (a.value != HVMPTM_no_delay_for_missed_ticks) &&
- (a.value != HVMPTM_no_missed_tick_accounting) )
+ if ( a.value > HVMPTM_one_missed_tick_pending )
goto param_fail;
break;
}
return;
missed_ticks = missed_ticks / (s_time_t) pt->period + 1;
- pt->pending_intr_nr += missed_ticks;
+ if ( mode_is(pt->vcpu->domain, no_missed_ticks_pending) )
+ pt->do_not_freeze = !pt->pending_intr_nr;
+ else
+ pt->pending_intr_nr += missed_ticks;
pt->scheduled += missed_ticks * pt->period;
}
spin_lock(&v->arch.hvm_vcpu.tm_lock);
list_for_each_entry ( pt, head, list )
- stop_timer(&pt->timer);
+ if ( !pt->do_not_freeze )
+ stop_timer(&pt->timer);
pt_freeze_time(v);
return;
}
+ pt->do_not_freeze = 0;
+
if ( pt->one_shot )
{
pt->enabled = 0;
}
else
{
- if ( mode_is(v->domain, no_missed_tick_accounting) )
+ if ( mode_is(v->domain, one_missed_tick_pending) )
{
pt->last_plt_gtime = hvm_get_guest_time(v);
pt->pending_intr_nr = 0; /* 'collapse' all missed ticks */
pt->enabled = 1;
pt->pending_intr_nr = 0;
+ pt->do_not_freeze = 0;
/* Periodic timer must be at least 0.9ms. */
if ( (period < 900000) && !one_shot )
struct list_head list;
char enabled;
char one_shot; /* one shot time */
+ char do_not_freeze;
u8 irq;
struct vcpu *vcpu; /* vcpu timer interrupt delivers to */
u32 pending_intr_nr; /* the couner for pending timer interrupts */
* As above, missed interrupts are delivered, but guest time always tracks
* wallclock (i.e., real) time while doing so.
* no_missed_ticks_pending:
- * No more than one missed interrupt is held pending, and guest time always
- * tracks wallclock (i.e., real) time.
+ * No missed interrupts are held pending. Instead, to ensure ticks are
+ * delivered at some non-zero rate, if we detect missed ticks then the
+ * internal tick alarm is not disabled if the VCPU is preempted during the
+ * next tick period.
+ * one_missed_tick_pending:
+ * Missed interrupts are collapsed together and delivered as one 'late tick'.
+ * Guest time always tracks wallclock (i.e., real) time.
*/
#define HVM_PARAM_TIMER_MODE 10
#define HVMPTM_delay_for_missed_ticks 0
#define HVMPTM_no_delay_for_missed_ticks 1
-#define HVMPTM_no_missed_tick_accounting 2
+#define HVMPTM_no_missed_ticks_pending 2
+#define HVMPTM_one_missed_tick_pending 3
#define HVM_NR_PARAMS 11