[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



>>> 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.
Also perhaps "... is being set"?

>+        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 ...

>+    }
 >
>-    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.

Also - comment style.

>@@ -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.

Jan


_______________________________________________
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®.