lkml.org 
[lkml]   [2007]   [Oct]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 11/11] KVM: Improve local apic timer wraparound handling
    Date
    From: Kevin Pedretti <kevin.pedretti@gmail.com>

    Better handle wrap-around cases when reading the APIC CCR
    (current count register). Also, if ICR is 0, CCR should also
    be 0... previously reading CCR before setting ICR would result
    in a large kinda-random number.

    Signed-off-by: Kevin Pedretti <kevin.pedretti@gmail.com>
    Signed-off-by: Avi Kivity <avi@qumranet.com>
    ---
    drivers/kvm/lapic.c | 36 ++++++++++++++++++++++++++----------
    1 files changed, 26 insertions(+), 10 deletions(-)

    diff --git a/drivers/kvm/lapic.c b/drivers/kvm/lapic.c
    index 443730e..238fcad 100644
    --- a/drivers/kvm/lapic.c
    +++ b/drivers/kvm/lapic.c
    @@ -494,12 +494,19 @@ static void apic_send_ipi(struct kvm_lapic *apic)

    static u32 apic_get_tmcct(struct kvm_lapic *apic)
    {
    - u32 counter_passed;
    - ktime_t passed, now = apic->timer.dev.base->get_time();
    - u32 tmcct = apic_get_reg(apic, APIC_TMICT);
    + u64 counter_passed;
    + ktime_t passed, now;
    + u32 tmcct;

    ASSERT(apic != NULL);

    + now = apic->timer.dev.base->get_time();
    + tmcct = apic_get_reg(apic, APIC_TMICT);
    +
    + /* if initial count is 0, current count should also be 0 */
    + if (tmcct == 0)
    + return 0;
    +
    if (unlikely(ktime_to_ns(now) <=
    ktime_to_ns(apic->timer.last_update))) {
    /* Wrap around */
    @@ -514,15 +521,24 @@ static u32 apic_get_tmcct(struct kvm_lapic *apic)

    counter_passed = div64_64(ktime_to_ns(passed),
    (APIC_BUS_CYCLE_NS * apic->timer.divide_count));
    - tmcct -= counter_passed;

    - if (tmcct <= 0) {
    - if (unlikely(!apic_lvtt_period(apic)))
    + if (counter_passed > tmcct) {
    + if (unlikely(!apic_lvtt_period(apic))) {
    + /* one-shot timers stick at 0 until reset */
    tmcct = 0;
    - else
    - do {
    - tmcct += apic_get_reg(apic, APIC_TMICT);
    - } while (tmcct <= 0);
    + } else {
    + /*
    + * periodic timers reset to APIC_TMICT when they
    + * hit 0. The while loop simulates this happening N
    + * times. (counter_passed %= tmcct) would also work,
    + * but might be slower or not work on 32-bit??
    + */
    + while (counter_passed > tmcct)
    + counter_passed -= tmcct;
    + tmcct -= counter_passed;
    + }
    + } else {
    + tmcct -= counter_passed;
    }

    return tmcct;
    --
    1.5.3
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2007-10-21 13:15    [W:0.042 / U:0.768 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site