[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v2 2/3] x86/vlapic: Keep timer running when switching between one-shot and periodic mode



On Thu, Aug 03, 2017 at 09:21:57AM -0600, Jan Beulich wrote:
> >>> Anthony PERARD <anthony.perard@xxxxxxxxxx> 07/18/17 7:12 PM >>>
> >@@ -678,18 +679,29 @@ static void vlapic_tdt_pt_cb(struct vcpu *v, void 
> >*data)
> >static void vlapic_update_timer(struct vlapic *vlapic, uint32_t lvtt);
> >{
> >uint64_t period;
> >-    uint64_t delta;
> >-    bool is_periodic;
> >+    uint64_t delta = 0;
> >+    bool is_oneshot, is_periodic;
>  >
> >is_periodic = (lvtt & APIC_TIMER_MODE_MASK) == APIC_TIMER_MODE_PERIODIC;
> >+    is_oneshot = (lvtt & APIC_TIMER_MODE_MASK) == APIC_TIMER_MODE_ONESHOT;
>  >
>      >period = (uint64_t)vlapic_get_reg(vlapic, APIC_TMICT)
> >* APIC_BUS_CYCLE_NS * vlapic->hw.timer_divisor;
>  >
> >/* Calculate the next time the timer should trigger an interrupt. */
> >-    delta = period;
> >+    if ( period && vlapic->timer_last_update )
> >+    {
> >+        uint64_t time_passed = hvm_get_guest_time(current)
> >+            - vlapic->timer_last_update;
> >+
> >+        /* This depends of the previous mode, if a new mode is set */
> 
> It's nice that you add such a comment, but this really documents a
> requirement the caller has to fulfill, so I'm afraid it's somewhat misplaced.

It's a comment about why I'm using vlapic_lvtt_period() here instead of
the local variable is_periodic. Also, the requirement for the caller is
already documented.

> >+        if ( vlapic_lvtt_period(vlapic) )
> >+            time_passed %= period;
> >+        if ( time_passed < period )
> >+            delta = period - time_passed;
> 
> Why is this second step not also dependent on the timer previously
> having been periodic? This is particularly relevant in connection with ...

This is the same algorithme as the one used to calculate the current
value of the counter register TMCCT. The second steps only depends on
when the initial-counter register TMICT was set and what is value was.
Since the periodicity of the timer is been take care in the first step,
it does not matter any more if the timer was previously periodic or
one-shot.

"period" here is the initial value of the counter and "time_passed"
correspond to how much time have passed since TMCCT have been reset to
the value in TMICT, either because TMICT was set or because the timer
was periodic.

> >+    }
>  >
> >-    if ( delta )
> >+    if ( delta && (is_oneshot || is_periodic) )
> >{
> >TRACE_2_LONG_3D(TRC_HVM_EMUL_LAPIC_START_TIMER, TRC_PAR_LONG(delta),
> >TRC_PAR_LONG(is_periodic ? period : 0LL),
> >@@ -702,7 +714,11 @@ static void vlapic_update_timer(struct vlapic *vlapic, 
> >uint32_t lvtt);
> >is_periodic ? vlapic_pt_cb : NULL,
> >&vlapic->timer_last_update);
>  >
> >-        vlapic->timer_last_update = vlapic->pt.last_plt_gtime;
> >+        /* For the case where the timer was periodic and it is now
> >+         * one-shot, timer_last_update should be the value of the last time
> >+         * the interrupt was triggered.
> >+         */
> >+        vlapic->timer_last_update = vlapic->pt.last_plt_gtime + delta - 
> >period;
>  
> ,,, this. Note how the comment talks about a change from one-shot to
> periodic, but how the code does not obviously alter behavior in only that
> one case.

I need to think about it.

When TMICT is changed, delta == period, so the value is not altered.

When the timer mode is changed, delta and period are going to be
different. And the difference is going to be, how much time have passed
since TMICT was set or since the last time a periodic timer reach 0.

So the comment is inappropriate here. It might be usefull in the commit
message, and I may need a better comment on why I'm doing +delta-period.

> >@@ -818,6 +840,7 @@ static void vlapic_reg_write(struct vcpu *v,
> >if ( !vlapic_lvtt_oneshot(vlapic) && !vlapic_lvtt_period(vlapic) )
> >break;
>  >
> >+        vlapic->timer_last_update = hvm_get_guest_time(current);
> >vlapic_set_reg(vlapic, APIC_TMICT, val);
>  >
> >vlapic_update_timer(vlapic, vlapic_get_reg(vlapic, APIC_LVTT));
> 
> Why is this addition needed? vlapic_update_timer() sets timer_last_update
> anyway. As it looks all you want is the value to be non-zero, which can be
> done with less overhead and should be stated so in a comment.

This is not true, the value is used before been set. It is used to
calculate how much time have passed since tmict was set. Before been set
again, there is this:
time_passed = hvm_get_guest_time(current) - vlapic->timer_last_update;

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.